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