xref: /petsc/src/dm/dt/space/impls/sum/spacesum.c (revision 7d5fd1e4d9337468ad3f05b65b7facdcd2dfd2a4)
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,"Cannot change number of subspaces after setup called\n");
159   if (numSumSpaces == Ns) PetscFunctionReturn(0);
160   if (Ns >= 0) {
161     PetscInt s;
162     for (s=0; s<Ns; ++s) {
163       ierr = PetscSpaceDestroy(&sum->sumspaces[s]);CHKERRQ(ierr);
164     }
165     ierr = PetscFree(sum->sumspaces);CHKERRQ(ierr);
166   }
167 
168   Ns   = sum->numSumSpaces = numSumSpaces;
169   ierr = PetscCalloc1(Ns,&sum->sumspaces);CHKERRQ(ierr);
170   PetscFunctionReturn(0);
171 }
172 
173 static PetscErrorCode PetscSpaceSumGetConcatenate_Sum(PetscSpace sp,PetscBool *concatenate)
174 {
175   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
176 
177   PetscFunctionBegin;
178   *concatenate = sum->concatenate;
179   PetscFunctionReturn(0);
180 }
181 
182 static PetscErrorCode PetscSpaceSumSetConcatenate_Sum(PetscSpace sp,PetscBool concatenate)
183 {
184   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
185 
186   PetscFunctionBegin;
187   if (sum->setupCalled) SETERRQ(PetscObjectComm((PetscObject)sp),PETSC_ERR_ARG_WRONGSTATE,"Cannot change space concatenation after setup called.\n");
188 
189   sum->concatenate = concatenate;
190   PetscFunctionReturn(0);
191 }
192 
193 static PetscErrorCode PetscSpaceSumGetSubspace_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   if (Ns < 0) SETERRQ(PetscObjectComm((PetscObject)space),PETSC_ERR_ARG_WRONGSTATE,"Must call PetscSpaceSumSetNumSubspaces() first\n");
200   if (s<0 || s>=Ns) SETERRQ1 (PetscObjectComm((PetscObject)space),PETSC_ERR_ARG_OUTOFRANGE,"Invalid subspace number %D\n",subspace);
201 
202   *subspace = sum->sumspaces[s];
203   PetscFunctionReturn(0);
204 }
205 
206 static PetscErrorCode PetscSpaceSumSetSubspace_Sum(PetscSpace space,PetscInt s,PetscSpace subspace)
207 {
208   PetscSpace_Sum *sum = (PetscSpace_Sum*)space->data;
209   PetscInt       Ns   = sum->numSumSpaces;
210   PetscErrorCode ierr;
211 
212   PetscFunctionBegin;
213   if (sum->setupCalled) SETERRQ(PetscObjectComm((PetscObject)space),PETSC_ERR_ARG_WRONGSTATE,"Cannot change subspace after setup called\n");
214   if (Ns < 0) SETERRQ(PetscObjectComm((PetscObject)space),PETSC_ERR_ARG_WRONGSTATE,"Must call PetscSpaceSumSetNumSubspaces() first\n");
215   if (s < 0 || s >= Ns) SETERRQ1(PetscObjectComm((PetscObject)space),PETSC_ERR_ARG_OUTOFRANGE,"Invalid subspace number %D\n",subspace);
216 
217   ierr              = PetscObjectReference((PetscObject)subspace);CHKERRQ(ierr);
218   ierr              = PetscSpaceDestroy(&sum->sumspaces[s]);CHKERRQ(ierr);
219   sum->sumspaces[s] = subspace;
220   PetscFunctionReturn(0);
221 }
222 
223 static PetscErrorCode PetscSpaceSetFromOptions_Sum(PetscOptionItems *PetscOptionsObject,PetscSpace sp)
224 {
225   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
226   PetscInt       Ns,Nc,Nv,deg,i;
227   PetscBool      concatenate = PETSC_TRUE;
228   const char     *prefix;
229   PetscErrorCode ierr;
230 
231   PetscFunctionBegin;
232   ierr = PetscSpaceGetNumVariables(sp,&Nv);CHKERRQ(ierr);
233   if (!Nv) PetscFunctionReturn(0);
234   ierr = PetscSpaceGetNumComponents(sp,&Nc);CHKERRQ(ierr);
235   ierr = PetscSpaceSumGetNumSubspaces(sp,&Ns);CHKERRQ(ierr);
236   ierr = PetscSpaceGetDegree(sp,&deg,NULL);CHKERRQ(ierr);
237   Ns   = (Ns == PETSC_DEFAULT) ? 1 : Ns;
238 
239   ierr = PetscOptionsHead(PetscOptionsObject,"PetscSpace sum options");CHKERRQ(ierr);
240   ierr = PetscOptionsBoundedInt("-petscspace_sum_spaces","The number of subspaces","PetscSpaceSumSetNumSubspaces",Ns,&Ns,NULL,0);CHKERRQ(ierr);
241   ierr = PetscOptionsBool("-petscspace_sum_concatenate","Subspaces are concatenated components of the final space","PetscSpaceSumSetFromOptions",
242                           concatenate,&concatenate,NULL);CHKERRQ(ierr);
243   ierr = PetscOptionsTail();CHKERRQ(ierr);
244 
245   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);
246   if (Ns != sum->numSumSpaces) {
247     ierr = PetscSpaceSumSetNumSubspaces(sp,Ns);CHKERRQ(ierr);
248   }
249   ierr = PetscObjectGetOptionsPrefix((PetscObject)sp,&prefix);CHKERRQ(ierr);
250   for (i=0; i<Ns; ++i) {
251     PetscInt   sNv;
252     PetscSpace subspace;
253 
254     ierr = PetscSpaceSumGetSubspace(sp,i,&subspace);CHKERRQ(ierr);
255     if (!subspace) {
256       char subspacePrefix[256];
257 
258       ierr = PetscSpaceCreate(PetscObjectComm((PetscObject)sp),&subspace);CHKERRQ(ierr);
259       ierr = PetscObjectSetOptionsPrefix((PetscObject)subspace,prefix);CHKERRQ(ierr);
260       ierr = PetscSNPrintf(subspacePrefix,256,"subspace%d_",i);CHKERRQ(ierr);
261       ierr = PetscObjectAppendOptionsPrefix((PetscObject)subspace,subspacePrefix);CHKERRQ(ierr);
262     } else {
263       ierr = PetscObjectReference((PetscObject)subspace);CHKERRQ(ierr);
264     }
265     ierr = PetscSpaceSetFromOptions(subspace);CHKERRQ(ierr);
266     ierr = PetscSpaceGetNumVariables(subspace,&sNv);CHKERRQ(ierr);
267     if (!sNv) SETERRQ1(PetscObjectComm((PetscObject)sp),PETSC_ERR_ARG_WRONGSTATE,"Subspace %D has not been set properly, number of variables is 0.\n",i);
268     ierr = PetscSpaceSumSetSubspace(sp,i,subspace);CHKERRQ(ierr);
269     ierr = PetscSpaceDestroy(&subspace);CHKERRQ(ierr);
270   }
271   PetscFunctionReturn(0);
272 }
273 
274 static PetscErrorCode PetscSpaceSetUp_Sum(PetscSpace sp)
275 {
276   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
277   PetscBool      concatenate = PETSC_TRUE;
278   PetscInt       Nv,Ns,Nc,i,sum_Nc = 0,deg = PETSC_MIN_INT,maxDeg = PETSC_MIN_INT;
279   PetscErrorCode ierr;
280 
281   PetscFunctionBegin;
282   if (sum->setupCalled) PetscFunctionReturn(0);
283 
284   ierr = PetscSpaceGetNumVariables(sp,&Nv);CHKERRQ(ierr);
285   ierr = PetscSpaceGetNumComponents(sp,&Nc);CHKERRQ(ierr);
286   ierr = PetscSpaceSumGetNumSubspaces(sp,&Ns);CHKERRQ(ierr);
287   if (Ns == PETSC_DEFAULT) {
288     Ns   = 1;
289     ierr = PetscSpaceSumSetNumSubspaces(sp,Ns);CHKERRQ(ierr);
290   }
291   if (!Ns && Nv) SETERRQ(PetscObjectComm((PetscObject)sp),PETSC_ERR_ARG_OUTOFRANGE,"Cannot have zero subspaces\n");
292 
293   for (i=0; i<Ns; ++i) {
294     PetscInt   sNv,sNc,iDeg,iMaxDeg;
295     PetscSpace si;
296 
297     ierr = PetscSpaceSumGetSubspace(sp,i,&si);CHKERRQ(ierr);
298     ierr = PetscSpaceSetUp(si);CHKERRQ(ierr);
299     ierr = PetscSpaceGetNumVariables(si,&sNv);CHKERRQ(ierr);
300     if (sNv != Nv) SETERRQ3(PetscObjectComm((PetscObject)sp),PETSC_ERR_ARG_WRONGSTATE,"Subspace %D has %D variables, space has %D.\n",i,sNv,Nv);
301     ierr = PetscSpaceGetNumComponents(si,&sNc);CHKERRQ(ierr);
302     if (i == 0 && sNc == Nc) concatenate = PETSC_FALSE;
303     sum_Nc += sNc;
304     ierr    = PetscSpaceSumGetSubspace(sp,i,&si);CHKERRQ(ierr);
305     ierr    = PetscSpaceGetDegree(si,&iDeg,&iMaxDeg);CHKERRQ(ierr);
306     deg     = PetscMax(deg,iDeg);
307     maxDeg  = PetscMax(maxDeg,iMaxDeg);
308   }
309 
310   if (concatenate) {
311     if (sum_Nc != Nc) {
312       SETERRQ2(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);
313     }
314   } else {
315     if (sum_Nc != Ns*Nc) SETERRQ(PetscObjectComm((PetscObject)sp),PETSC_ERR_ARG_OUTOFRANGE,"Subspaces must have same number of components as the target space.");
316   }
317 
318   sp->degree       = deg;
319   sp->maxDegree    = maxDeg;
320   sum->concatenate = concatenate;
321   sum->setupCalled = PETSC_TRUE;
322   PetscFunctionReturn(0);
323 }
324 
325 static PetscErrorCode PetscSpaceSumView_Ascii(PetscSpace sp,PetscViewer v)
326 {
327   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
328   PetscBool      concatenate = sum->concatenate;
329   PetscInt       i,Ns         = sum->numSumSpaces;
330   PetscErrorCode ierr;
331 
332   PetscFunctionBegin;
333   if (concatenate) {
334     ierr = PetscViewerASCIIPrintf(v,"Sum space of %D concatenated subspaces\n",Ns);CHKERRQ(ierr);
335   } else {
336     ierr = PetscViewerASCIIPrintf(v,"Sum space of %D subspaces\n",Ns);CHKERRQ(ierr);
337   }
338   for (i=0; i<Ns; ++i) {
339     ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr);
340     ierr = PetscSpaceView(sum->sumspaces[i],v);CHKERRQ(ierr);
341     ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr);
342   }
343   PetscFunctionReturn(0);
344 }
345 
346 static PetscErrorCode PetscSpaceView_Sum(PetscSpace sp,PetscViewer viewer)
347 {
348   PetscBool      iascii;
349   PetscErrorCode ierr;
350 
351   PetscFunctionBegin;
352   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
353   if (iascii) {
354     ierr = PetscSpaceSumView_Ascii(sp,viewer);CHKERRQ(ierr);
355   }
356   PetscFunctionReturn(0);
357 }
358 
359 static PetscErrorCode PetscSpaceDestroy_Sum(PetscSpace sp)
360 {
361   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
362   PetscInt       i,Ns   = sum->numSumSpaces;
363   PetscErrorCode ierr;
364 
365   PetscFunctionBegin;
366   for (i=0; i<Ns; ++i) {
367     ierr = PetscSpaceDestroy(&sum->sumspaces[i]);CHKERRQ(ierr);
368   }
369   ierr = PetscFree(sum->sumspaces);CHKERRQ(ierr);
370   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetSubspace_C",NULL);CHKERRQ(ierr);
371   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetSubspace_C",NULL);CHKERRQ(ierr);
372   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetNumSubspaces_C",NULL);CHKERRQ(ierr);
373   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetNumSubspaces_C",NULL);CHKERRQ(ierr);
374   ierr = PetscFree(sum);CHKERRQ(ierr);
375   PetscFunctionReturn(0);
376 }
377 
378 static PetscErrorCode PetscSpaceGetDimension_Sum(PetscSpace sp,PetscInt *dim)
379 {
380   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
381   PetscInt       i,d = 0,Ns = sum->numSumSpaces;
382   PetscErrorCode ierr;
383 
384   PetscFunctionBegin;
385   ierr = PetscSpaceSetUp(sp);CHKERRQ(ierr);
386 
387   for (i=0; i<Ns; ++i) {
388     PetscInt id;
389 
390     ierr = PetscSpaceGetDimension(sum->sumspaces[i],&id);CHKERRQ(ierr);
391     d   += id;
392   }
393 
394   *dim = d;
395   PetscFunctionReturn(0);
396 }
397 
398 static PetscErrorCode PetscSpaceEvaluate_Sum(PetscSpace sp,PetscInt npoints,const PetscReal points[],PetscReal B[],PetscReal D[],PetscReal H[])
399 {
400   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
401   PetscBool      concatenate = sum->concatenate;
402   DM             dm = sp->dm;
403   PetscInt       Nc = sp->Nc,Nv = sp->Nv,Ns = sum->numSumSpaces;
404   PetscInt       i,s,offset,ncoffset,pdimfull,numelB,numelD,numelH;
405   PetscReal      *sB = NULL,*sD = NULL,*sH = NULL;
406   PetscErrorCode ierr;
407 
408   PetscFunctionBegin;
409   if (!sum->setupCalled) {
410     ierr = PetscSpaceSetUp(sp);CHKERRQ(ierr);
411   }
412   ierr   = PetscSpaceGetDimension(sp,&pdimfull);CHKERRQ(ierr);
413   numelB = npoints*pdimfull*Nc;
414   numelD = numelB*Nv;
415   numelH = numelD*Nv;
416   if (B || D || H) {
417     ierr = DMGetWorkArray(dm,numelB,MPIU_REAL,&sB);CHKERRQ(ierr);
418   }
419   if (D || H) {
420     ierr = DMGetWorkArray(dm,numelD,MPIU_REAL,&sD);CHKERRQ(ierr);
421   }
422   if (H) {
423     ierr = DMGetWorkArray(dm,numelH,MPIU_REAL,&sH);CHKERRQ(ierr);
424   }
425   if (B)
426     for (i=0; i<numelB; ++i) B[i] = 0.;
427   if (D)
428     for (i=0; i<numelD; ++i) D[i] = 0.;
429   if (H)
430     for (i=0; i<numelH; ++i) H[i] = 0.;
431 
432   for (s=0,offset=0,ncoffset=0; s<Ns; ++s) {
433     PetscInt sNv,spdim,sNc,p;
434 
435     ierr = PetscSpaceGetNumVariables(sum->sumspaces[s],&sNv);CHKERRQ(ierr);
436     ierr = PetscSpaceGetNumComponents(sum->sumspaces[s],&sNc);CHKERRQ(ierr);
437     ierr = PetscSpaceGetDimension(sum->sumspaces[s],&spdim);CHKERRQ(ierr);
438     if (offset + spdim > pdimfull) SETERRQ(PetscObjectComm((PetscObject)sp),PETSC_ERR_ARG_OUTOFRANGE,"Subspace dimensions exceed target space dimension.\n");
439     ierr = PetscSpaceEvaluate(sum->sumspaces[s],npoints,points,sB,sD,sH);CHKERRQ(ierr);
440     if (B || D || H) {
441       for (p=0; p<npoints; ++p) {
442         PetscInt j;
443 
444         for (j=0; j<spdim; ++j) {
445           PetscInt c;
446 
447           for (c=0; c<sNc; ++c) {
448             PetscInt compoffset,BInd,sBInd;
449 
450             compoffset = concatenate ? c+ncoffset : c;
451             BInd       = (p*pdimfull + j + offset)*Nc + compoffset;
452             sBInd      = (p*spdim + j)*sNc + c;
453             if (B) B[BInd] += sB[sBInd];
454             if (D || H) {
455               PetscInt v;
456 
457               for (v=0; v<Nv; ++v) {
458                 PetscInt DInd,sDInd;
459 
460                 DInd  = BInd*Nv + v;
461                 sDInd = sBInd*Nv + v;
462                 if (D) D[DInd] +=sD[sDInd];
463                 if (H) {
464                   PetscInt v2;
465 
466                   for (v2=0; v2<Nv; ++v2) {
467                     PetscInt HInd,sHInd;
468 
469                     HInd     = DInd*Nv + v2;
470                     sHInd    = sDInd*Nv + v2;
471                     H[HInd] += sH[sHInd];
472                   }
473                 }
474               }
475             }
476           }
477         }
478       }
479     }
480     offset   += spdim;
481     ncoffset += sNc;
482   }
483 
484   if (H) {
485     ierr = DMRestoreWorkArray(dm,numelH,MPIU_REAL,&sH);CHKERRQ(ierr);
486   }
487   if (D || H) {
488     ierr = DMRestoreWorkArray(dm,numelD,MPIU_REAL,&sD);CHKERRQ(ierr);
489   }
490   if (B || D || H) {
491     ierr = DMRestoreWorkArray(dm,numelB,MPIU_REAL,&sB);CHKERRQ(ierr);
492   }
493   PetscFunctionReturn(0);
494 }
495 
496 static PetscErrorCode PetscSpaceInitialize_Sum(PetscSpace sp)
497 {
498   PetscErrorCode ierr;
499 
500   PetscFunctionBegin;
501   sp->ops->setfromoptions = PetscSpaceSetFromOptions_Sum;
502   sp->ops->setup          = PetscSpaceSetUp_Sum;
503   sp->ops->view           = PetscSpaceView_Sum;
504   sp->ops->destroy        = PetscSpaceDestroy_Sum;
505   sp->ops->getdimension   = PetscSpaceGetDimension_Sum;
506   sp->ops->evaluate       = PetscSpaceEvaluate_Sum;
507 
508   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetNumSubspaces_C",PetscSpaceSumGetNumSubspaces_Sum);CHKERRQ(ierr);
509   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetNumSubspaces_C",PetscSpaceSumSetNumSubspaces_Sum);CHKERRQ(ierr);
510   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetSubspace_C",PetscSpaceSumGetSubspace_Sum);CHKERRQ(ierr);
511   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetSubspace_C",PetscSpaceSumSetSubspace_Sum);CHKERRQ(ierr);
512   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetConcatenate_C",PetscSpaceSumGetConcatenate_Sum);CHKERRQ(ierr);
513   ierr = PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetConcatenate_C",PetscSpaceSumSetConcatenate_Sum);CHKERRQ(ierr);
514   PetscFunctionReturn(0);
515 }
516 
517 /*MC
518   PETSCSPACESUM = "sum" - A PetscSpace object that encapsulates a sum of subspaces.
519   That sum can either be direct or concatenate a concatenation.For example if A and B are spaces each with 2 components,
520   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
521   same number of variables.
522 
523 Level: intermediate
524 
525 .seealso: PetscSpaceType, PetscSpaceCreate(), PetscSpaceSetType()
526 M*/
527 PETSC_EXTERN PetscErrorCode PetscSpaceCreate_Sum(PetscSpace sp)
528 {
529   PetscSpace_Sum *sum;
530   PetscErrorCode ierr;
531 
532   PetscFunctionBegin;
533   PetscValidHeaderSpecific(sp,PETSCSPACE_CLASSID,1);
534   ierr     = PetscNewLog(sp,&sum);CHKERRQ(ierr);
535   sp->data = sum;
536   ierr     = PetscSpaceInitialize_Sum(sp);CHKERRQ(ierr);
537   PetscFunctionReturn(0);
538 }
539 
540 PETSC_EXTERN PetscErrorCode PetscSpaceCreateSum(PetscInt numSubspaces,const PetscSpace subspaces[],PetscBool concatenate,PetscSpace *sumSpace)
541 {
542   PetscInt       i,Nv,Nc = 0;
543   PetscErrorCode ierr;
544 
545   PetscFunctionBegin;
546   if (sumSpace) {
547     ierr = PetscSpaceDestroy(sumSpace);CHKERRQ(ierr);
548   }
549   ierr = PetscSpaceCreate(PetscObjectComm((PetscObject)subspaces[0]),sumSpace);CHKERRQ(ierr);
550   ierr = PetscSpaceSetType(*sumSpace,PETSCSPACESUM);CHKERRQ(ierr);
551   ierr = PetscSpaceSumSetNumSubspaces(*sumSpace,numSubspaces);CHKERRQ(ierr);
552   ierr = PetscSpaceSumSetConcatenate(*sumSpace,concatenate);CHKERRQ(ierr);
553   for (i=0; i<numSubspaces; ++i) {
554     PetscInt sNc;
555 
556     ierr = PetscSpaceSumSetSubspace(*sumSpace,i,subspaces[i]);CHKERRQ(ierr);
557     ierr = PetscSpaceGetNumComponents(subspaces[i],&sNc);CHKERRQ(ierr);
558     if (concatenate) Nc += sNc;
559     else Nc = sNc;
560   }
561   ierr = PetscSpaceGetNumVariables(subspaces[0],&Nv);CHKERRQ(ierr);
562   ierr = PetscSpaceSetNumComponents(*sumSpace,Nc);CHKERRQ(ierr);
563   ierr = PetscSpaceSetNumVariables(*sumSpace,Nv);CHKERRQ(ierr);
564   ierr = PetscSpaceSetUp(*sumSpace);CHKERRQ(ierr);
565 
566   PetscFunctionReturn(0);
567 }
568