xref: /petsc/src/dm/dt/space/impls/sum/spacesum.c (revision d092c84b752daaa800a5a26c90ada1294ab10274)
1*d092c84bSBrandon Whitchurch #include <petsc/private/petscfeimpl.h> /*I "petscfe.h" I*/
2*d092c84bSBrandon Whitchurch /*@
3*d092c84bSBrandon Whitchurch   PetscSpaceSumGetNumSubspaces - Get the number of spaces in the sum
4*d092c84bSBrandon Whitchurch 
5*d092c84bSBrandon Whitchurch   Input Parameter:
6*d092c84bSBrandon Whitchurch   . sp  - the function space object
7*d092c84bSBrandon Whitchurch 
8*d092c84bSBrandon Whitchurch   Output Parameter:
9*d092c84bSBrandon Whitchurch   . numSumSpaces - the number of spaces
10*d092c84bSBrandon Whitchurch 
11*d092c84bSBrandon Whitchurch Level: intermediate
12*d092c84bSBrandon Whitchurch 
13*d092c84bSBrandon Whitchurch .seealso: PetscSpaceSumSetNumSubspaces(), PetscSpaceSetDegree(), PetscSpaceSetNumVariables()
14*d092c84bSBrandon Whitchurch @*/
15*d092c84bSBrandon Whitchurch PetscErrorCode PetscSpaceSumGetNumSubspaces(PetscSpace sp,PetscInt *numSumSpaces)
16*d092c84bSBrandon Whitchurch {
17*d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
18*d092c84bSBrandon Whitchurch 
19*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
20*d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp,PETSCSPACE_CLASSID,1);
21*d092c84bSBrandon Whitchurch   PetscValidIntPointer(numSumSpaces,2);
22*d092c84bSBrandon Whitchurch   ierr = PetscTryMethod(sp,"PetscSpaceSumGetNumSubspaces_C",(PetscSpace,PetscInt*),(sp,numSumSpaces));CHKERRQ(ierr);
23*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
24*d092c84bSBrandon Whitchurch }
25*d092c84bSBrandon Whitchurch 
26*d092c84bSBrandon Whitchurch /*@
27*d092c84bSBrandon Whitchurch   PetscSpaceSumSetNumSubspaces - Set the number of spaces in the sum
28*d092c84bSBrandon Whitchurch 
29*d092c84bSBrandon Whitchurch   Input Parameters:
30*d092c84bSBrandon Whitchurch   + sp  - the function space object
31*d092c84bSBrandon Whitchurch   - numSumSpaces - the number of spaces
32*d092c84bSBrandon Whitchurch 
33*d092c84bSBrandon Whitchurch Level: intermediate
34*d092c84bSBrandon Whitchurch 
35*d092c84bSBrandon Whitchurch .seealso: PetscSpaceSumGetNumSubspaces(), PetscSpaceSetDegree(), PetscSpaceSetNumVariables()
36*d092c84bSBrandon Whitchurch @*/
37*d092c84bSBrandon Whitchurch PetscErrorCode PetscSpaceSumSetNumSubspaces(PetscSpace sp,PetscInt numSumSpaces)
38*d092c84bSBrandon Whitchurch {
39*d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
40*d092c84bSBrandon Whitchurch 
41*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
42*d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp,PETSCSPACE_CLASSID,1);
43*d092c84bSBrandon Whitchurch   ierr = PetscTryMethod(sp,"PetscSpaceSumSetNumSubspaces_C",(PetscSpace,PetscInt),(sp,numSumSpaces));CHKERRQ(ierr);
44*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
45*d092c84bSBrandon Whitchurch }
46*d092c84bSBrandon Whitchurch 
47*d092c84bSBrandon Whitchurch /*@
48*d092c84bSBrandon Whitchurch  PetscSpaceSumGetConcatenate - Get the concatenate flag for this space.
49*d092c84bSBrandon 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,
50*d092c84bSBrandon Whitchurch  or direct sum space will have the same number of components as its subspaces .
51*d092c84bSBrandon Whitchurch 
52*d092c84bSBrandon Whitchurch  Input Parameters:
53*d092c84bSBrandon Whitchurch  . sp - the function space object
54*d092c84bSBrandon Whitchurch 
55*d092c84bSBrandon Whitchurch  Output Parameters:
56*d092c84bSBrandon Whitchurch  . concatenate - flag indicating whether subspaces are concatenated.
57*d092c84bSBrandon Whitchurch 
58*d092c84bSBrandon Whitchurch Level: intermediate
59*d092c84bSBrandon Whitchurch 
60*d092c84bSBrandon Whitchurch .seealso: PetscSpaceSumSetConcatenate()
61*d092c84bSBrandon Whitchurch @*/
62*d092c84bSBrandon Whitchurch PetscErrorCode PetscSpaceSumGetConcatenate(PetscSpace sp,PetscBool *concatenate)
63*d092c84bSBrandon Whitchurch {
64*d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
65*d092c84bSBrandon Whitchurch 
66*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
67*d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp,PETSCSPACE_CLASSID,1);
68*d092c84bSBrandon Whitchurch   ierr = PetscTryMethod(sp,"PetscSpaceSumGetConcatenate_C",(PetscSpace,PetscBool*),(sp,concatenate));CHKERRQ(ierr);
69*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
70*d092c84bSBrandon Whitchurch }
71*d092c84bSBrandon Whitchurch 
72*d092c84bSBrandon Whitchurch /*@
73*d092c84bSBrandon Whitchurch   PetscSpaceSumSetConcatenate - Sets the concatenate flag for this space.
74*d092c84bSBrandon 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,
75*d092c84bSBrandon Whitchurch  or direct sum space will have the same number of components as its subspaces .
76*d092c84bSBrandon Whitchurch 
77*d092c84bSBrandon Whitchurch  Input Parameters:
78*d092c84bSBrandon Whitchurch   + sp - the function space object
79*d092c84bSBrandon Whitchurch   - concatenate - are subspaces concatenated components (true) or direct summands (false)
80*d092c84bSBrandon Whitchurch 
81*d092c84bSBrandon Whitchurch Level: intermediate
82*d092c84bSBrandon Whitchurch .seealso: PetscSpaceSumGetConcatenate()
83*d092c84bSBrandon Whitchurch @*/
84*d092c84bSBrandon Whitchurch PetscErrorCode PetscSpaceSumSetConcatenate(PetscSpace sp,PetscBool concatenate)
85*d092c84bSBrandon Whitchurch {
86*d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
87*d092c84bSBrandon Whitchurch 
88*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
89*d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp,PETSCSPACE_CLASSID,1);
90*d092c84bSBrandon Whitchurch   ierr = PetscTryMethod(sp,"PetscSpaceSumSetConcatenate_C",(PetscSpace,PetscBool),(sp,concatenate));CHKERRQ(ierr);
91*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
92*d092c84bSBrandon Whitchurch }
93*d092c84bSBrandon Whitchurch 
94*d092c84bSBrandon Whitchurch /*@
95*d092c84bSBrandon Whitchurch   PetscSpaceSumGetSubspace - Get a space in the sum
96*d092c84bSBrandon Whitchurch 
97*d092c84bSBrandon Whitchurch   Input Parameters:
98*d092c84bSBrandon Whitchurch   + sp - the function space object
99*d092c84bSBrandon Whitchurch   - s  - The space number
100*d092c84bSBrandon Whitchurch 
101*d092c84bSBrandon Whitchurch   Output Parameter:
102*d092c84bSBrandon Whitchurch   . subsp - the PetscSpace
103*d092c84bSBrandon Whitchurch 
104*d092c84bSBrandon Whitchurch Level: intermediate
105*d092c84bSBrandon Whitchurch 
106*d092c84bSBrandon Whitchurch .seealso: PetscSpaceSumSetSubspace(), PetscSpaceSetDegree(), PetscSpaceSetNumVariables()
107*d092c84bSBrandon Whitchurch @*/
108*d092c84bSBrandon Whitchurch PetscErrorCode PetscSpaceSumGetSubspace(PetscSpace sp,PetscInt s,PetscSpace *subsp)
109*d092c84bSBrandon Whitchurch {
110*d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
111*d092c84bSBrandon Whitchurch 
112*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
113*d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp,PETSCSPACE_CLASSID,1);
114*d092c84bSBrandon Whitchurch   PetscValidPointer(subsp,3);
115*d092c84bSBrandon Whitchurch   ierr = PetscTryMethod(sp,"PetscSpaceSumGetSubspace_C",(PetscSpace,PetscInt,PetscSpace*),(sp,s,subsp));CHKERRQ(ierr);
116*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
117*d092c84bSBrandon Whitchurch }
118*d092c84bSBrandon Whitchurch 
119*d092c84bSBrandon Whitchurch /*@
120*d092c84bSBrandon Whitchurch   PetscSpaceSumSetSubspace - Set a space in the sum
121*d092c84bSBrandon Whitchurch 
122*d092c84bSBrandon Whitchurch   Input Parameters:
123*d092c84bSBrandon Whitchurch   + sp    - the function space object
124*d092c84bSBrandon Whitchurch   . s     - The space number
125*d092c84bSBrandon Whitchurch   - subsp - the number of spaces
126*d092c84bSBrandon Whitchurch 
127*d092c84bSBrandon Whitchurch Level: intermediate
128*d092c84bSBrandon Whitchurch 
129*d092c84bSBrandon Whitchurch .seealso: PetscSpaceSumGetSubspace(), PetscSpaceSetDegree(), PetscSpaceSetNumVariables()
130*d092c84bSBrandon Whitchurch @*/
131*d092c84bSBrandon Whitchurch PetscErrorCode PetscSpaceSumSetSubspace(PetscSpace sp,PetscInt s,PetscSpace subsp)
132*d092c84bSBrandon Whitchurch {
133*d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
134*d092c84bSBrandon Whitchurch 
135*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
136*d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp,PETSCSPACE_CLASSID,1);
137*d092c84bSBrandon Whitchurch   if (subsp) PetscValidHeaderSpecific(subsp,PETSCSPACE_CLASSID,3);
138*d092c84bSBrandon Whitchurch   ierr = PetscTryMethod(sp,"PetscSpaceSumSetSubspace_C",(PetscSpace,PetscInt,PetscSpace),(sp,s,subsp));CHKERRQ(ierr);
139*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
140*d092c84bSBrandon Whitchurch }
141*d092c84bSBrandon Whitchurch 
142*d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceSumGetNumSubspaces_Sum(PetscSpace space,PetscInt *numSumSpaces)
143*d092c84bSBrandon Whitchurch {
144*d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)space->data;
145*d092c84bSBrandon Whitchurch 
146*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
147*d092c84bSBrandon Whitchurch   *numSumSpaces = sum->numSumSpaces;
148*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
149*d092c84bSBrandon Whitchurch }
150*d092c84bSBrandon Whitchurch 
151*d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceSumSetNumSubspaces_Sum(PetscSpace space,PetscInt numSumSpaces)
152*d092c84bSBrandon Whitchurch {
153*d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)space->data;
154*d092c84bSBrandon Whitchurch   PetscInt       Ns   = sum->numSumSpaces;
155*d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
156*d092c84bSBrandon Whitchurch 
157*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
158*d092c84bSBrandon Whitchurch   if (sum->setupCalled) SETERRQ(PetscObjectComm((PetscObject)space),PETSC_ERR_ARG_WRONGSTATE,
159*d092c84bSBrandon Whitchurch                                 "Cannot change number of subspaces after setup called\n");
160*d092c84bSBrandon Whitchurch   if (numSumSpaces == Ns) PetscFunctionReturn(0);
161*d092c84bSBrandon Whitchurch   if (Ns >= 0) {
162*d092c84bSBrandon Whitchurch     PetscInt s;
163*d092c84bSBrandon Whitchurch     for (s=0; s<Ns; ++s) {
164*d092c84bSBrandon Whitchurch       ierr = PetscSpaceDestroy(&sum->sumspaces[s]);CHKERRQ(ierr);
165*d092c84bSBrandon Whitchurch     }
166*d092c84bSBrandon Whitchurch     ierr = PetscFree(sum->sumspaces);CHKERRQ(ierr);
167*d092c84bSBrandon Whitchurch   }
168*d092c84bSBrandon Whitchurch 
169*d092c84bSBrandon Whitchurch   Ns   = sum->numSumSpaces = numSumSpaces;
170*d092c84bSBrandon Whitchurch   ierr = PetscCalloc1(Ns,&sum->sumspaces);CHKERRQ(ierr);
171*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
172*d092c84bSBrandon Whitchurch }
173*d092c84bSBrandon Whitchurch 
174*d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceSumGetConcatenate_Sum(PetscSpace sp,PetscBool *concatenate)
175*d092c84bSBrandon Whitchurch {
176*d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
177*d092c84bSBrandon Whitchurch 
178*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
179*d092c84bSBrandon Whitchurch   *concatenate = sum->concatenate;
180*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
181*d092c84bSBrandon Whitchurch }
182*d092c84bSBrandon Whitchurch 
183*d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceSumSetConcatenate_Sum(PetscSpace sp,PetscBool concatenate)
184*d092c84bSBrandon Whitchurch {
185*d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
186*d092c84bSBrandon Whitchurch 
187*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
188*d092c84bSBrandon Whitchurch   if (sum->setupCalled) SETERRQ(PetscObjectComm((PetscObject)sp),PETSC_ERR_ARG_WRONGSTATE,"Cannot change space concatenation after setup called.\n");
189*d092c84bSBrandon Whitchurch 
190*d092c84bSBrandon Whitchurch   sum->concatenate = concatenate;
191*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
192*d092c84bSBrandon Whitchurch }
193*d092c84bSBrandon Whitchurch 
194*d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceSumGetSubspace_Sum(PetscSpace space,PetscInt s,PetscSpace *subspace)
195*d092c84bSBrandon Whitchurch {
196*d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)space->data;
197*d092c84bSBrandon Whitchurch   PetscInt       Ns   = sum->numSumSpaces;
198*d092c84bSBrandon Whitchurch 
199*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
200*d092c84bSBrandon Whitchurch   if (Ns < 0) SETERRQ(PetscObjectComm((PetscObject)space),PETSC_ERR_ARG_WRONGSTATE,"Must call PetscSpaceSumSetNumSubspaces() first\n");
201*d092c84bSBrandon Whitchurch   if (s<0 || s>=Ns) SETERRQ1 (PetscObjectComm((PetscObject)space),PETSC_ERR_ARG_OUTOFRANGE,"Invalid subspace number %D\n",subspace);
202*d092c84bSBrandon Whitchurch 
203*d092c84bSBrandon Whitchurch   *subspace = sum->sumspaces[s];
204*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
205*d092c84bSBrandon Whitchurch }
206*d092c84bSBrandon Whitchurch 
207*d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceSumSetSubspace_Sum(PetscSpace space,PetscInt s,PetscSpace subspace)
208*d092c84bSBrandon Whitchurch {
209*d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)space->data;
210*d092c84bSBrandon Whitchurch   PetscInt       Ns   = sum->numSumSpaces;
211*d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
212*d092c84bSBrandon Whitchurch 
213*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
214*d092c84bSBrandon Whitchurch   if (sum->setupCalled) SETERRQ(PetscObjectComm((PetscObject)space),PETSC_ERR_ARG_WRONGSTATE,"Cannot change subspace after setup called\n");
215*d092c84bSBrandon Whitchurch   if (Ns < 0) SETERRQ(PetscObjectComm((PetscObject)space),PETSC_ERR_ARG_WRONGSTATE,"Must call PetscSpaceSumSetNumSubspaces() first\n");
216*d092c84bSBrandon Whitchurch   if (s < 0 || s >= Ns) SETERRQ1(PetscObjectComm((PetscObject)space),PETSC_ERR_ARG_OUTOFRANGE,"Invalid subspace number %D\n",subspace);
217*d092c84bSBrandon Whitchurch 
218*d092c84bSBrandon Whitchurch   ierr              = PetscObjectReference((PetscObject)subspace);CHKERRQ(ierr);
219*d092c84bSBrandon Whitchurch   ierr              = PetscSpaceDestroy(&sum->sumspaces[s]);CHKERRQ(ierr);
220*d092c84bSBrandon Whitchurch   sum->sumspaces[s] = subspace;
221*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
222*d092c84bSBrandon Whitchurch }
223*d092c84bSBrandon Whitchurch 
224*d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceSetFromOptions_Sum(PetscOptionItems *PetscOptionsObject,PetscSpace sp)
225*d092c84bSBrandon Whitchurch {
226*d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
227*d092c84bSBrandon Whitchurch   PetscInt       Ns,Nc,Nv,deg,i;
228*d092c84bSBrandon Whitchurch   PetscBool      concatenate = PETSC_TRUE;
229*d092c84bSBrandon Whitchurch   const char     *prefix;
230*d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
231*d092c84bSBrandon Whitchurch 
232*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
233*d092c84bSBrandon Whitchurch   ierr = PetscSpaceGetNumVariables(sp,&Nv);CHKERRQ(ierr);
234*d092c84bSBrandon Whitchurch   if (!Nv) PetscFunctionReturn(0);
235*d092c84bSBrandon Whitchurch   ierr = PetscSpaceGetNumComponents(sp,&Nc);CHKERRQ(ierr);
236*d092c84bSBrandon Whitchurch   ierr = PetscSpaceSumGetNumSubspaces(sp,&Ns);CHKERRQ(ierr);
237*d092c84bSBrandon Whitchurch   ierr = PetscSpaceGetDegree(sp,&deg,NULL);CHKERRQ(ierr);
238*d092c84bSBrandon Whitchurch   Ns   = (Ns == PETSC_DEFAULT) ? 1 : Ns;
239*d092c84bSBrandon Whitchurch 
240*d092c84bSBrandon Whitchurch   ierr = PetscOptionsHead(PetscOptionsObject,"PetscSpace sum options");CHKERRQ(ierr);
241*d092c84bSBrandon Whitchurch   ierr = PetscOptionsBoundedInt("-petscspace_sum_spaces","The number of subspaces","PetscSpaceSumSetNumSubspaces",Ns,&Ns,NULL,0);CHKERRQ(ierr);
242*d092c84bSBrandon Whitchurch   ierr = PetscOptionsBool("-petscspace_sum_concatenate","Subspaces are concatenated components of the final space","PetscSpaceSumSetFromOptions",
243*d092c84bSBrandon Whitchurch                           concatenate,&concatenate,NULL);CHKERRQ(ierr);
244*d092c84bSBrandon Whitchurch   ierr = PetscOptionsTail();CHKERRQ(ierr);
245*d092c84bSBrandon Whitchurch 
246*d092c84bSBrandon Whitchurch   if (Ns < 0 || (Nv > 0 && Ns == 0)) SETERRQ1(PetscObjectComm((PetscObject)sp),PETSC_ERR_ARG_OUTOFRANGE,"Cannot have a sum space of %D spaces\n",Ns);
247*d092c84bSBrandon Whitchurch   if (Ns != sum->numSumSpaces) {
248*d092c84bSBrandon Whitchurch     ierr = PetscSpaceSumSetNumSubspaces(sp,Ns);CHKERRQ(ierr);
249*d092c84bSBrandon Whitchurch   }
250*d092c84bSBrandon Whitchurch   ierr = PetscObjectGetOptionsPrefix((PetscObject)sp,&prefix);CHKERRQ(ierr);
251*d092c84bSBrandon Whitchurch   for (i=0; i<Ns; ++i) {
252*d092c84bSBrandon Whitchurch     PetscInt   sNv;
253*d092c84bSBrandon Whitchurch     PetscSpace subspace;
254*d092c84bSBrandon Whitchurch 
255*d092c84bSBrandon Whitchurch     ierr = PetscSpaceSumGetSubspace(sp,i,&subspace);CHKERRQ(ierr);
256*d092c84bSBrandon Whitchurch     if (!subspace) {
257*d092c84bSBrandon Whitchurch       char subspacePrefix[256];
258*d092c84bSBrandon Whitchurch 
259*d092c84bSBrandon Whitchurch       ierr = PetscSpaceCreate(PetscObjectComm((PetscObject)sp),&subspace);CHKERRQ(ierr);
260*d092c84bSBrandon Whitchurch       ierr = PetscObjectSetOptionsPrefix((PetscObject)subspace,prefix);CHKERRQ(ierr);
261*d092c84bSBrandon Whitchurch       ierr = PetscSNPrintf(subspacePrefix,256,"subspace%d_",i);CHKERRQ(ierr);
262*d092c84bSBrandon Whitchurch       ierr = PetscObjectAppendOptionsPrefix((PetscObject)subspace,subspacePrefix);CHKERRQ(ierr);
263*d092c84bSBrandon Whitchurch     } else {
264*d092c84bSBrandon Whitchurch       ierr = PetscObjectReference((PetscObject)subspace);CHKERRQ(ierr);
265*d092c84bSBrandon Whitchurch     }
266*d092c84bSBrandon Whitchurch     ierr = PetscSpaceSetFromOptions(subspace);CHKERRQ(ierr);
267*d092c84bSBrandon Whitchurch     ierr = PetscSpaceGetNumVariables(subspace,&sNv);CHKERRQ(ierr);
268*d092c84bSBrandon Whitchurch     if (!sNv) SETERRQ1(PetscObjectComm(
269*d092c84bSBrandon Whitchurch                          (PetscObject)sp),PETSC_ERR_ARG_WRONGSTATE,"Subspace %D has not been set properly, number of variables is 0.\n",i);
270*d092c84bSBrandon Whitchurch     ierr = PetscSpaceSumSetSubspace(sp,i,subspace);CHKERRQ(ierr);
271*d092c84bSBrandon Whitchurch     ierr = PetscSpaceDestroy(&subspace);CHKERRQ(ierr);
272*d092c84bSBrandon Whitchurch   }
273*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
274*d092c84bSBrandon Whitchurch }
275*d092c84bSBrandon Whitchurch 
276*d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceSetUp_Sum(PetscSpace sp)
277*d092c84bSBrandon Whitchurch {
278*d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
279*d092c84bSBrandon Whitchurch   PetscBool      concatenate = PETSC_TRUE;
280*d092c84bSBrandon Whitchurch   PetscInt       Nv,Ns,Nc,i,sum_Nc = 0,deg = PETSC_MIN_INT,maxDeg = PETSC_MIN_INT;
281*d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
282*d092c84bSBrandon Whitchurch 
283*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
284*d092c84bSBrandon Whitchurch   if (sum->setupCalled) PetscFunctionReturn(0);
285*d092c84bSBrandon Whitchurch 
286*d092c84bSBrandon Whitchurch   ierr = PetscSpaceGetNumVariables(sp,&Nv);CHKERRQ(ierr);
287*d092c84bSBrandon Whitchurch   ierr = PetscSpaceGetNumComponents(sp,&Nc);CHKERRQ(ierr);
288*d092c84bSBrandon Whitchurch   ierr = PetscSpaceSumGetNumSubspaces(sp,&Ns);CHKERRQ(ierr);
289*d092c84bSBrandon Whitchurch   if (Ns == PETSC_DEFAULT) {
290*d092c84bSBrandon Whitchurch     Ns   = 1;
291*d092c84bSBrandon Whitchurch     ierr = PetscSpaceSumSetNumSubspaces(sp,Ns);CHKERRQ(ierr);
292*d092c84bSBrandon Whitchurch   }
293*d092c84bSBrandon Whitchurch   if (!Ns && Nv) SETERRQ(PetscObjectComm((PetscObject)sp),PETSC_ERR_ARG_OUTOFRANGE,"Cannot have zero subspaces\n");
294*d092c84bSBrandon Whitchurch 
295*d092c84bSBrandon Whitchurch   for (i=0; i<Ns; ++i) {
296*d092c84bSBrandon Whitchurch     PetscInt   sNv,sNc,iDeg,iMaxDeg;
297*d092c84bSBrandon Whitchurch     PetscSpace si;
298*d092c84bSBrandon Whitchurch 
299*d092c84bSBrandon Whitchurch     ierr = PetscSpaceSumGetSubspace(sp,i,&si);CHKERRQ(ierr);
300*d092c84bSBrandon Whitchurch     ierr = PetscSpaceSetUp(si);CHKERRQ(ierr);
301*d092c84bSBrandon Whitchurch     ierr = PetscSpaceGetNumVariables(si,&sNv);CHKERRQ(ierr);
302*d092c84bSBrandon Whitchurch     if (sNv != Nv) SETERRQ3(PetscObjectComm((PetscObject)sp),PETSC_ERR_ARG_WRONGSTATE,"Subspace %D has %D variables, space has %D.\n",i,sNv,Nv);
303*d092c84bSBrandon Whitchurch     ierr = PetscSpaceGetNumComponents(si,&sNc);CHKERRQ(ierr);
304*d092c84bSBrandon Whitchurch     if (i == 0 && sNc == Nc) concatenate = PETSC_FALSE;
305*d092c84bSBrandon Whitchurch     sum_Nc += sNc;
306*d092c84bSBrandon Whitchurch     ierr    = PetscSpaceSumGetSubspace(sp,i,&si);CHKERRQ(ierr);
307*d092c84bSBrandon Whitchurch     ierr    = PetscSpaceGetDegree(si,&iDeg,&iMaxDeg);CHKERRQ(ierr);
308*d092c84bSBrandon Whitchurch     deg     = PetscMax(deg,iDeg);
309*d092c84bSBrandon Whitchurch     maxDeg  = PetscMax(maxDeg,iMaxDeg);
310*d092c84bSBrandon Whitchurch   }
311*d092c84bSBrandon Whitchurch 
312*d092c84bSBrandon Whitchurch   if (concatenate) {
313*d092c84bSBrandon Whitchurch     if (sum_Nc != Nc) {
314*d092c84bSBrandon Whitchurch       SETERRQ2(PetscObjectComm((PetscObject)sp),PETSC_ERR_ARG_OUTOFRANGE,
315*d092c84bSBrandon Whitchurch                "Total number of subspace components (%D) does not match number of target space components (%D).",sum_Nc,Nc);
316*d092c84bSBrandon Whitchurch     }
317*d092c84bSBrandon Whitchurch   } else {
318*d092c84bSBrandon Whitchurch     if (sum_Nc != Ns*Nc) SETERRQ(PetscObjectComm(
319*d092c84bSBrandon Whitchurch                                    (PetscObject)sp),PETSC_ERR_ARG_OUTOFRANGE,"Subspaces must have same number of components as the target space.");
320*d092c84bSBrandon Whitchurch   }
321*d092c84bSBrandon Whitchurch 
322*d092c84bSBrandon Whitchurch   sp->degree       = deg;
323*d092c84bSBrandon Whitchurch   sp->maxDegree    = maxDeg;
324*d092c84bSBrandon Whitchurch   sum->concatenate = concatenate;
325*d092c84bSBrandon Whitchurch   sum->setupCalled = PETSC_TRUE;
326*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
327*d092c84bSBrandon Whitchurch }
328*d092c84bSBrandon Whitchurch 
329*d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceSumView_Ascii(PetscSpace sp,PetscViewer v)
330*d092c84bSBrandon Whitchurch {
331*d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
332*d092c84bSBrandon Whitchurch   PetscBool      concatenate = sum->concatenate;
333*d092c84bSBrandon Whitchurch   PetscInt       i,Ns         = sum->numSumSpaces;
334*d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
335*d092c84bSBrandon Whitchurch 
336*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
337*d092c84bSBrandon Whitchurch   if (concatenate) {
338*d092c84bSBrandon Whitchurch     ierr = PetscViewerASCIIPrintf(v,"Sum space of %D concatenated subspaces\n",Ns);CHKERRQ(ierr);
339*d092c84bSBrandon Whitchurch   } else {
340*d092c84bSBrandon Whitchurch     ierr = PetscViewerASCIIPrintf(v,"Sum space of %D subspaces\n",Ns);CHKERRQ(ierr);
341*d092c84bSBrandon Whitchurch   }
342*d092c84bSBrandon Whitchurch   for (i=0; i<Ns; ++i) {
343*d092c84bSBrandon Whitchurch     ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr);
344*d092c84bSBrandon Whitchurch     ierr = PetscSpaceView(sum->sumspaces[i],v);CHKERRQ(ierr);
345*d092c84bSBrandon Whitchurch     ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr);
346*d092c84bSBrandon Whitchurch   }
347*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
348*d092c84bSBrandon Whitchurch }
349*d092c84bSBrandon Whitchurch 
350*d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceView_Sum(PetscSpace sp,PetscViewer viewer)
351*d092c84bSBrandon Whitchurch {
352*d092c84bSBrandon Whitchurch   PetscBool      iascii;
353*d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
354*d092c84bSBrandon Whitchurch 
355*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
356*d092c84bSBrandon Whitchurch   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
357*d092c84bSBrandon Whitchurch   if (iascii) {
358*d092c84bSBrandon Whitchurch     ierr = PetscSpaceSumView_Ascii(sp,viewer);CHKERRQ(ierr);
359*d092c84bSBrandon Whitchurch   }
360*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
361*d092c84bSBrandon Whitchurch }
362*d092c84bSBrandon Whitchurch 
363*d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceDestroy_Sum(PetscSpace sp)
364*d092c84bSBrandon Whitchurch {
365*d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
366*d092c84bSBrandon Whitchurch   PetscInt       i,Ns   = sum->numSumSpaces;
367*d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
368*d092c84bSBrandon Whitchurch 
369*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
370*d092c84bSBrandon Whitchurch   for (i=0; i<Ns; ++i) {
371*d092c84bSBrandon Whitchurch     ierr = PetscSpaceDestroy(&sum->sumspaces[i]);CHKERRQ(ierr);
372*d092c84bSBrandon Whitchurch   }
373*d092c84bSBrandon Whitchurch   ierr = PetscFree(sum->sumspaces);CHKERRQ(ierr);
374*d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetSubspace_C",NULL);CHKERRQ(ierr);
375*d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetSubspace_C",NULL);CHKERRQ(ierr);
376*d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetNumSubspaces_C",NULL);CHKERRQ(ierr);
377*d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetNumSubspaces_C",NULL);CHKERRQ(ierr);
378*d092c84bSBrandon Whitchurch   ierr = PetscFree(sum);CHKERRQ(ierr);
379*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
380*d092c84bSBrandon Whitchurch }
381*d092c84bSBrandon Whitchurch 
382*d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceGetDimension_Sum(PetscSpace sp,PetscInt *dim)
383*d092c84bSBrandon Whitchurch {
384*d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
385*d092c84bSBrandon Whitchurch   PetscInt       i,d = 0,Ns = sum->numSumSpaces;
386*d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
387*d092c84bSBrandon Whitchurch 
388*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
389*d092c84bSBrandon Whitchurch   ierr = PetscSpaceSetUp(sp);CHKERRQ(ierr);
390*d092c84bSBrandon Whitchurch 
391*d092c84bSBrandon Whitchurch   for (i=0; i<Ns; ++i) {
392*d092c84bSBrandon Whitchurch     PetscInt id;
393*d092c84bSBrandon Whitchurch 
394*d092c84bSBrandon Whitchurch     ierr = PetscSpaceGetDimension(sum->sumspaces[i],&id);CHKERRQ(ierr);
395*d092c84bSBrandon Whitchurch     d   += id;
396*d092c84bSBrandon Whitchurch   }
397*d092c84bSBrandon Whitchurch 
398*d092c84bSBrandon Whitchurch   *dim = d;
399*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
400*d092c84bSBrandon Whitchurch }
401*d092c84bSBrandon Whitchurch 
402*d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceEvaluate_Sum(PetscSpace sp,PetscInt npoints,const PetscReal points[],PetscReal B[],PetscReal D[],PetscReal H[])
403*d092c84bSBrandon Whitchurch {
404*d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
405*d092c84bSBrandon Whitchurch   PetscBool      concatenate = sum->concatenate;
406*d092c84bSBrandon Whitchurch   DM             dm = sp->dm;
407*d092c84bSBrandon Whitchurch   PetscInt       Nc = sp->Nc,Nv = sp->Nv,Ns = sum->numSumSpaces;
408*d092c84bSBrandon Whitchurch   PetscInt       i,s,offset,ncoffset,pdimfull,numelB,numelD,numelH;
409*d092c84bSBrandon Whitchurch   PetscReal      *sB = NULL,*sD = NULL,*sH = NULL;
410*d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
411*d092c84bSBrandon Whitchurch 
412*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
413*d092c84bSBrandon Whitchurch   if (!sum->setupCalled) {
414*d092c84bSBrandon Whitchurch     ierr = PetscSpaceSetUp(sp);CHKERRQ(ierr);
415*d092c84bSBrandon Whitchurch   }
416*d092c84bSBrandon Whitchurch   ierr   = PetscSpaceGetDimension(sp,&pdimfull);CHKERRQ(ierr);
417*d092c84bSBrandon Whitchurch   numelB = npoints*pdimfull*Nc;
418*d092c84bSBrandon Whitchurch   numelD = numelB*Nv;
419*d092c84bSBrandon Whitchurch   numelH = numelD*Nv;
420*d092c84bSBrandon Whitchurch   if (B || D || H) {
421*d092c84bSBrandon Whitchurch     ierr = DMGetWorkArray(dm,numelB,MPIU_REAL,&sB);CHKERRQ(ierr);
422*d092c84bSBrandon Whitchurch   }
423*d092c84bSBrandon Whitchurch   if (D || H) {
424*d092c84bSBrandon Whitchurch     ierr = DMGetWorkArray(dm,numelD,MPIU_REAL,&sD);CHKERRQ(ierr);
425*d092c84bSBrandon Whitchurch   }
426*d092c84bSBrandon Whitchurch   if (H) {
427*d092c84bSBrandon Whitchurch     ierr = DMGetWorkArray(dm,numelH,MPIU_REAL,&sH);CHKERRQ(ierr);
428*d092c84bSBrandon Whitchurch   }
429*d092c84bSBrandon Whitchurch   if (B)
430*d092c84bSBrandon Whitchurch     for (i=0; i<numelB; ++i) B[i] = 0.;
431*d092c84bSBrandon Whitchurch   if (D)
432*d092c84bSBrandon Whitchurch     for (i=0; i<numelD; ++i) D[i] = 0.;
433*d092c84bSBrandon Whitchurch   if (H)
434*d092c84bSBrandon Whitchurch     for (i=0; i<numelH; ++i) H[i] = 0.;
435*d092c84bSBrandon Whitchurch 
436*d092c84bSBrandon Whitchurch   for (s=0,offset=0,ncoffset=0; s<Ns; ++s) {
437*d092c84bSBrandon Whitchurch     PetscInt sNv,spdim,sNc,p;
438*d092c84bSBrandon Whitchurch 
439*d092c84bSBrandon Whitchurch     ierr = PetscSpaceGetNumVariables(sum->sumspaces[s],&sNv);CHKERRQ(ierr);
440*d092c84bSBrandon Whitchurch     ierr = PetscSpaceGetNumComponents(sum->sumspaces[s],&sNc);CHKERRQ(ierr);
441*d092c84bSBrandon Whitchurch     ierr = PetscSpaceGetDimension(sum->sumspaces[s],&spdim);CHKERRQ(ierr);
442*d092c84bSBrandon Whitchurch     if (offset + spdim > pdimfull) SETERRQ(PetscObjectComm(
443*d092c84bSBrandon Whitchurch                                              (PetscObject)sp),PETSC_ERR_ARG_OUTOFRANGE,"Subspace dimensions exceed target space dimension.\n");
444*d092c84bSBrandon Whitchurch     ierr = PetscSpaceEvaluate(sum->sumspaces[s],npoints,points,sB,sD,sH);CHKERRQ(ierr);
445*d092c84bSBrandon Whitchurch     if (B || D || H) {
446*d092c84bSBrandon Whitchurch       for (p=0; p<npoints; ++p) {
447*d092c84bSBrandon Whitchurch         PetscInt j;
448*d092c84bSBrandon Whitchurch 
449*d092c84bSBrandon Whitchurch         for (j=0; j<spdim; ++j) {
450*d092c84bSBrandon Whitchurch           PetscInt c;
451*d092c84bSBrandon Whitchurch 
452*d092c84bSBrandon Whitchurch           for (c=0; c<sNc; ++c) {
453*d092c84bSBrandon Whitchurch             PetscInt compoffset,BInd,sBInd;
454*d092c84bSBrandon Whitchurch 
455*d092c84bSBrandon Whitchurch             compoffset = concatenate ? c+ncoffset : c;
456*d092c84bSBrandon Whitchurch             BInd       = (p*pdimfull + j + offset)*Nc + compoffset;
457*d092c84bSBrandon Whitchurch             sBInd      = (p*spdim + j)*sNc + c;
458*d092c84bSBrandon Whitchurch             if (B) B[BInd] += sB[sBInd];
459*d092c84bSBrandon Whitchurch             if (D || H) {
460*d092c84bSBrandon Whitchurch               PetscInt v;
461*d092c84bSBrandon Whitchurch 
462*d092c84bSBrandon Whitchurch               for (v=0; v<Nv; ++v) {
463*d092c84bSBrandon Whitchurch                 PetscInt DInd,sDInd;
464*d092c84bSBrandon Whitchurch 
465*d092c84bSBrandon Whitchurch                 DInd  = BInd*Nv + v;
466*d092c84bSBrandon Whitchurch                 sDInd = sBInd*Nv + v;
467*d092c84bSBrandon Whitchurch                 if (D) D[DInd] +=sD[sDInd];
468*d092c84bSBrandon Whitchurch                 if (H) {
469*d092c84bSBrandon Whitchurch                   PetscInt v2;
470*d092c84bSBrandon Whitchurch 
471*d092c84bSBrandon Whitchurch                   for (v2=0; v2<Nv; ++v2) {
472*d092c84bSBrandon Whitchurch                     PetscInt HInd,sHInd;
473*d092c84bSBrandon Whitchurch 
474*d092c84bSBrandon Whitchurch                     HInd     = DInd*Nv + v2;
475*d092c84bSBrandon Whitchurch                     sHInd    = sDInd*Nv + v2;
476*d092c84bSBrandon Whitchurch                     H[HInd] += sH[sHInd];
477*d092c84bSBrandon Whitchurch                   }
478*d092c84bSBrandon Whitchurch                 }
479*d092c84bSBrandon Whitchurch               }
480*d092c84bSBrandon Whitchurch             }
481*d092c84bSBrandon Whitchurch           }
482*d092c84bSBrandon Whitchurch         }
483*d092c84bSBrandon Whitchurch       }
484*d092c84bSBrandon Whitchurch     }
485*d092c84bSBrandon Whitchurch     offset   += spdim;
486*d092c84bSBrandon Whitchurch     ncoffset += sNc;
487*d092c84bSBrandon Whitchurch   }
488*d092c84bSBrandon Whitchurch 
489*d092c84bSBrandon Whitchurch   if (H) {
490*d092c84bSBrandon Whitchurch     ierr = DMRestoreWorkArray(dm,numelH,MPIU_REAL,&sH);CHKERRQ(ierr);
491*d092c84bSBrandon Whitchurch   }
492*d092c84bSBrandon Whitchurch   if (D || H) {
493*d092c84bSBrandon Whitchurch     ierr = DMRestoreWorkArray(dm,numelD,MPIU_REAL,&sD);CHKERRQ(ierr);
494*d092c84bSBrandon Whitchurch   }
495*d092c84bSBrandon Whitchurch   if (B || D || H) {
496*d092c84bSBrandon Whitchurch     ierr = DMRestoreWorkArray(dm,numelB,MPIU_REAL,&sB);CHKERRQ(ierr);
497*d092c84bSBrandon Whitchurch   }
498*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
499*d092c84bSBrandon Whitchurch }
500*d092c84bSBrandon Whitchurch 
501*d092c84bSBrandon Whitchurch static PetscErrorCode PetscSpaceInitialize_Sum(PetscSpace sp)
502*d092c84bSBrandon Whitchurch {
503*d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
504*d092c84bSBrandon Whitchurch 
505*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
506*d092c84bSBrandon Whitchurch   sp->ops->setfromoptions = PetscSpaceSetFromOptions_Sum;
507*d092c84bSBrandon Whitchurch   sp->ops->setup          = PetscSpaceSetUp_Sum;
508*d092c84bSBrandon Whitchurch   sp->ops->view           = PetscSpaceView_Sum;
509*d092c84bSBrandon Whitchurch   sp->ops->destroy        = PetscSpaceDestroy_Sum;
510*d092c84bSBrandon Whitchurch   sp->ops->getdimension   = PetscSpaceGetDimension_Sum;
511*d092c84bSBrandon Whitchurch   sp->ops->evaluate       = PetscSpaceEvaluate_Sum;
512*d092c84bSBrandon Whitchurch 
513*d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetNumSubspaces_C",PetscSpaceSumGetNumSubspaces_Sum);CHKERRQ(ierr);
514*d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetNumSubspaces_C",PetscSpaceSumSetNumSubspaces_Sum);CHKERRQ(ierr);
515*d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetSubspace_C",PetscSpaceSumGetSubspace_Sum);CHKERRQ(ierr);
516*d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetSubspace_C",PetscSpaceSumSetSubspace_Sum);CHKERRQ(ierr);
517*d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetConcatenate_C",PetscSpaceSumGetConcatenate_Sum);CHKERRQ(ierr);
518*d092c84bSBrandon Whitchurch   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetConcatenate_C",PetscSpaceSumSetConcatenate_Sum);CHKERRQ(ierr);
519*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
520*d092c84bSBrandon Whitchurch }
521*d092c84bSBrandon Whitchurch 
522*d092c84bSBrandon Whitchurch /*MC
523*d092c84bSBrandon Whitchurch   PETSCSPACESUM = "sum" - A PetscSpace object that encapsulates a sum of subspaces.
524*d092c84bSBrandon Whitchurch   That sum can either be direct or concatenate a concatenation.For example if A and B are spaces each with 2 components,
525*d092c84bSBrandon 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
526*d092c84bSBrandon Whitchurch   same number of variables.
527*d092c84bSBrandon Whitchurch 
528*d092c84bSBrandon Whitchurch Level: intermediate
529*d092c84bSBrandon Whitchurch 
530*d092c84bSBrandon Whitchurch .seealso: PetscSpaceType, PetscSpaceCreate(), PetscSpaceSetType()
531*d092c84bSBrandon Whitchurch M*/
532*d092c84bSBrandon Whitchurch PETSC_EXTERN PetscErrorCode PetscSpaceCreate_Sum(PetscSpace sp)
533*d092c84bSBrandon Whitchurch {
534*d092c84bSBrandon Whitchurch   PetscSpace_Sum *sum;
535*d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
536*d092c84bSBrandon Whitchurch 
537*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
538*d092c84bSBrandon Whitchurch   PetscValidHeaderSpecific(sp,PETSCSPACE_CLASSID,1);
539*d092c84bSBrandon Whitchurch   ierr     = PetscNewLog(sp,&sum);CHKERRQ(ierr);
540*d092c84bSBrandon Whitchurch   sp->data = sum;
541*d092c84bSBrandon Whitchurch   ierr     = PetscSpaceInitialize_Sum(sp);CHKERRQ(ierr);
542*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
543*d092c84bSBrandon Whitchurch }
544*d092c84bSBrandon Whitchurch 
545*d092c84bSBrandon Whitchurch PETSC_EXTERN PetscErrorCode PetscSpaceCreateSum(PetscInt numSubspaces,const PetscSpace subspaces[],PetscBool concatenate,PetscSpace *sumSpace)
546*d092c84bSBrandon Whitchurch {
547*d092c84bSBrandon Whitchurch   PetscInt       i,Nv,Nc = 0;
548*d092c84bSBrandon Whitchurch   PetscErrorCode ierr;
549*d092c84bSBrandon Whitchurch 
550*d092c84bSBrandon Whitchurch   PetscFunctionBegin;
551*d092c84bSBrandon Whitchurch   if (sumSpace) {
552*d092c84bSBrandon Whitchurch     ierr = PetscSpaceDestroy(sumSpace);CHKERRQ(ierr);
553*d092c84bSBrandon Whitchurch   }
554*d092c84bSBrandon Whitchurch   ierr = PetscSpaceCreate(PetscObjectComm((PetscObject)subspaces[0]),sumSpace);CHKERRQ(ierr);
555*d092c84bSBrandon Whitchurch   ierr = PetscSpaceSetType(*sumSpace,PETSCSPACESUM);CHKERRQ(ierr);
556*d092c84bSBrandon Whitchurch   ierr = PetscSpaceSumSetNumSubspaces(*sumSpace,numSubspaces);CHKERRQ(ierr);
557*d092c84bSBrandon Whitchurch   ierr = PetscSpaceSumSetConcatenate(*sumSpace,concatenate);CHKERRQ(ierr);
558*d092c84bSBrandon Whitchurch   for (i=0; i<numSubspaces; ++i) {
559*d092c84bSBrandon Whitchurch     PetscInt sNc;
560*d092c84bSBrandon Whitchurch 
561*d092c84bSBrandon Whitchurch     ierr = PetscSpaceSumSetSubspace(*sumSpace,i,subspaces[i]);CHKERRQ(ierr);
562*d092c84bSBrandon Whitchurch     ierr = PetscSpaceGetNumComponents(subspaces[i],&sNc);CHKERRQ(ierr);
563*d092c84bSBrandon Whitchurch     if (concatenate) Nc += sNc;
564*d092c84bSBrandon Whitchurch     else Nc = sNc;
565*d092c84bSBrandon Whitchurch   }
566*d092c84bSBrandon Whitchurch   ierr = PetscSpaceGetNumVariables(subspaces[0],&Nv);CHKERRQ(ierr);
567*d092c84bSBrandon Whitchurch   ierr = PetscSpaceSetNumComponents(*sumSpace,Nc);CHKERRQ(ierr);
568*d092c84bSBrandon Whitchurch   ierr = PetscSpaceSetNumVariables(*sumSpace,Nv);CHKERRQ(ierr);
569*d092c84bSBrandon Whitchurch   ierr = PetscSpaceSetUp(*sumSpace);CHKERRQ(ierr);
570*d092c84bSBrandon Whitchurch 
571*d092c84bSBrandon Whitchurch   PetscFunctionReturn(0);
572*d092c84bSBrandon Whitchurch }
573