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