Actual source code: spacesum.c
1: #include <petsc/private/petscfeimpl.h>
2: /*@
3: PetscSpaceSumGetNumSubspaces - Get the number of spaces in the sum
5: Input Parameter:
6: . sp - the function space object
8: Output Parameter:
9: . numSumSpaces - the number of spaces
11: Level: intermediate
13: .seealso: `PETSCSPACESUM`, `PetscSpace`, `PetscSpaceSumSetNumSubspaces()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()`
14: @*/
15: PetscErrorCode PetscSpaceSumGetNumSubspaces(PetscSpace sp, PetscInt *numSumSpaces)
16: {
17: PetscFunctionBegin;
20: PetscTryMethod(sp, "PetscSpaceSumGetNumSubspaces_C", (PetscSpace, PetscInt *), (sp, numSumSpaces));
21: PetscFunctionReturn(PETSC_SUCCESS);
22: }
24: /*@
25: PetscSpaceSumSetNumSubspaces - Set the number of spaces in the sum
27: Input Parameters:
28: + sp - the function space object
29: - numSumSpaces - the number of spaces
31: Level: intermediate
33: .seealso: `PETSCSPACESUM`, `PetscSpace`, `PetscSpaceSumGetNumSubspaces()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()`
34: @*/
35: PetscErrorCode PetscSpaceSumSetNumSubspaces(PetscSpace sp, PetscInt numSumSpaces)
36: {
37: PetscFunctionBegin;
39: PetscTryMethod(sp, "PetscSpaceSumSetNumSubspaces_C", (PetscSpace, PetscInt), (sp, numSumSpaces));
40: PetscFunctionReturn(PETSC_SUCCESS);
41: }
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 .
48: Input Parameter:
49: . sp - the function space object
51: Output Parameter:
52: . concatenate - flag indicating whether subspaces are concatenated.
54: Level: intermediate
56: .seealso: `PETSCSPACESUM`, `PetscSpace`, `PetscSpaceSumSetConcatenate()`
57: @*/
58: PetscErrorCode PetscSpaceSumGetConcatenate(PetscSpace sp, PetscBool *concatenate)
59: {
60: PetscFunctionBegin;
62: PetscTryMethod(sp, "PetscSpaceSumGetConcatenate_C", (PetscSpace, PetscBool *), (sp, concatenate));
63: PetscFunctionReturn(PETSC_SUCCESS);
64: }
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 .
71: Input Parameters:
72: + sp - the function space object
73: - concatenate - are subspaces concatenated components (true) or direct summands (false)
75: Level: intermediate
77: .seealso: `PETSCSPACESUM`, `PetscSpace`, `PetscSpaceSumGetConcatenate()`
78: @*/
79: PetscErrorCode PetscSpaceSumSetConcatenate(PetscSpace sp, PetscBool concatenate)
80: {
81: PetscFunctionBegin;
83: PetscTryMethod(sp, "PetscSpaceSumSetConcatenate_C", (PetscSpace, PetscBool), (sp, concatenate));
84: PetscFunctionReturn(PETSC_SUCCESS);
85: }
87: /*@
88: PetscSpaceSumGetSubspace - Get a space in the sum
90: Input Parameters:
91: + sp - the function space object
92: - s - The space number
94: Output Parameter:
95: . subsp - the PetscSpace
97: Level: intermediate
99: .seealso: `PETSCSPACESUM`, `PetscSpace`, `PetscSpaceSumSetSubspace()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()`
100: @*/
101: PetscErrorCode PetscSpaceSumGetSubspace(PetscSpace sp, PetscInt s, PetscSpace *subsp)
102: {
103: PetscFunctionBegin;
106: PetscTryMethod(sp, "PetscSpaceSumGetSubspace_C", (PetscSpace, PetscInt, PetscSpace *), (sp, s, subsp));
107: PetscFunctionReturn(PETSC_SUCCESS);
108: }
110: /*@
111: PetscSpaceSumSetSubspace - Set a space in the sum
113: Input Parameters:
114: + sp - the function space object
115: . s - The space number
116: - subsp - the number of spaces
118: Level: intermediate
120: .seealso: `PETSCSPACESUM`, `PetscSpace`, `PetscSpaceSumGetSubspace()`, `PetscSpaceSetDegree()`, `PetscSpaceSetNumVariables()`
121: @*/
122: PetscErrorCode PetscSpaceSumSetSubspace(PetscSpace sp, PetscInt s, PetscSpace subsp)
123: {
124: PetscFunctionBegin;
127: PetscTryMethod(sp, "PetscSpaceSumSetSubspace_C", (PetscSpace, PetscInt, PetscSpace), (sp, s, subsp));
128: PetscFunctionReturn(PETSC_SUCCESS);
129: }
131: static PetscErrorCode PetscSpaceSumGetNumSubspaces_Sum(PetscSpace space, PetscInt *numSumSpaces)
132: {
133: PetscSpace_Sum *sum = (PetscSpace_Sum *)space->data;
135: PetscFunctionBegin;
136: *numSumSpaces = sum->numSumSpaces;
137: PetscFunctionReturn(PETSC_SUCCESS);
138: }
140: static PetscErrorCode PetscSpaceSumSetNumSubspaces_Sum(PetscSpace space, PetscInt numSumSpaces)
141: {
142: PetscSpace_Sum *sum = (PetscSpace_Sum *)space->data;
143: PetscInt Ns = sum->numSumSpaces;
145: PetscFunctionBegin;
146: PetscCheck(!sum->setupCalled, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Cannot change number of subspaces after setup called");
147: if (numSumSpaces == Ns) PetscFunctionReturn(PETSC_SUCCESS);
148: if (Ns >= 0) {
149: PetscInt s;
150: for (s = 0; s < Ns; ++s) PetscCall(PetscSpaceDestroy(&sum->sumspaces[s]));
151: PetscCall(PetscFree(sum->sumspaces));
152: }
154: Ns = sum->numSumSpaces = numSumSpaces;
155: PetscCall(PetscCalloc1(Ns, &sum->sumspaces));
156: PetscFunctionReturn(PETSC_SUCCESS);
157: }
159: static PetscErrorCode PetscSpaceSumGetConcatenate_Sum(PetscSpace sp, PetscBool *concatenate)
160: {
161: PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
163: PetscFunctionBegin;
164: *concatenate = sum->concatenate;
165: PetscFunctionReturn(PETSC_SUCCESS);
166: }
168: static PetscErrorCode PetscSpaceSumSetConcatenate_Sum(PetscSpace sp, PetscBool concatenate)
169: {
170: PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
172: PetscFunctionBegin;
173: PetscCheck(!sum->setupCalled, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Cannot change space concatenation after setup called.");
175: sum->concatenate = concatenate;
176: PetscFunctionReturn(PETSC_SUCCESS);
177: }
179: static PetscErrorCode PetscSpaceSumGetSubspace_Sum(PetscSpace space, PetscInt s, PetscSpace *subspace)
180: {
181: PetscSpace_Sum *sum = (PetscSpace_Sum *)space->data;
182: PetscInt Ns = sum->numSumSpaces;
184: PetscFunctionBegin;
185: PetscCheck(Ns >= 0, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Must call PetscSpaceSumSetNumSubspaces() first");
186: PetscCheck(s >= 0 && s < Ns, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_OUTOFRANGE, "Invalid subspace number %" PetscInt_FMT, s);
188: *subspace = sum->sumspaces[s];
189: PetscFunctionReturn(PETSC_SUCCESS);
190: }
192: static PetscErrorCode PetscSpaceSumSetSubspace_Sum(PetscSpace space, PetscInt s, PetscSpace subspace)
193: {
194: PetscSpace_Sum *sum = (PetscSpace_Sum *)space->data;
195: PetscInt Ns = sum->numSumSpaces;
197: PetscFunctionBegin;
198: PetscCheck(!sum->setupCalled, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Cannot change subspace after setup called");
199: PetscCheck(Ns >= 0, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_WRONGSTATE, "Must call PetscSpaceSumSetNumSubspaces() first");
200: PetscCheck(s >= 0 && s < Ns, PetscObjectComm((PetscObject)space), PETSC_ERR_ARG_OUTOFRANGE, "Invalid subspace number %" PetscInt_FMT, s);
202: PetscCall(PetscObjectReference((PetscObject)subspace));
203: PetscCall(PetscSpaceDestroy(&sum->sumspaces[s]));
204: sum->sumspaces[s] = subspace;
205: PetscFunctionReturn(PETSC_SUCCESS);
206: }
208: static PetscErrorCode PetscSpaceSetFromOptions_Sum(PetscSpace sp, PetscOptionItems *PetscOptionsObject)
209: {
210: PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
211: PetscInt Ns, Nc, Nv, deg, i;
212: PetscBool concatenate = PETSC_TRUE;
213: const char *prefix;
215: PetscFunctionBegin;
216: PetscCall(PetscSpaceGetNumVariables(sp, &Nv));
217: if (!Nv) PetscFunctionReturn(PETSC_SUCCESS);
218: PetscCall(PetscSpaceGetNumComponents(sp, &Nc));
219: PetscCall(PetscSpaceSumGetNumSubspaces(sp, &Ns));
220: PetscCall(PetscSpaceGetDegree(sp, °, NULL));
221: Ns = (Ns == PETSC_DEFAULT) ? 1 : Ns;
223: PetscOptionsHeadBegin(PetscOptionsObject, "PetscSpace sum options");
224: PetscCall(PetscOptionsBoundedInt("-petscspace_sum_spaces", "The number of subspaces", "PetscSpaceSumSetNumSubspaces", Ns, &Ns, NULL, 0));
225: PetscCall(PetscOptionsBool("-petscspace_sum_concatenate", "Subspaces are concatenated components of the final space", "PetscSpaceSumSetFromOptions", concatenate, &concatenate, NULL));
226: PetscOptionsHeadEnd();
228: PetscCheck(Ns >= 0 && (Nv <= 0 || Ns != 0), PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have a sum space of %" PetscInt_FMT " spaces", Ns);
229: if (Ns != sum->numSumSpaces) PetscCall(PetscSpaceSumSetNumSubspaces(sp, Ns));
230: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)sp, &prefix));
231: for (i = 0; i < Ns; ++i) {
232: PetscInt sNv;
233: PetscSpace subspace;
235: PetscCall(PetscSpaceSumGetSubspace(sp, i, &subspace));
236: if (!subspace) {
237: char subspacePrefix[256];
239: PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)sp), &subspace));
240: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)subspace, prefix));
241: PetscCall(PetscSNPrintf(subspacePrefix, 256, "sumcomp_%" PetscInt_FMT "_", i));
242: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)subspace, subspacePrefix));
243: } else PetscCall(PetscObjectReference((PetscObject)subspace));
244: PetscCall(PetscSpaceSetFromOptions(subspace));
245: PetscCall(PetscSpaceGetNumVariables(subspace, &sNv));
246: PetscCheck(sNv, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Subspace %" PetscInt_FMT " has not been set properly, number of variables is 0.", i);
247: PetscCall(PetscSpaceSumSetSubspace(sp, i, subspace));
248: PetscCall(PetscSpaceDestroy(&subspace));
249: }
250: PetscFunctionReturn(PETSC_SUCCESS);
251: }
253: static PetscErrorCode PetscSpaceSetUp_Sum(PetscSpace sp)
254: {
255: PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
256: PetscBool concatenate = PETSC_TRUE;
257: PetscBool uniform;
258: PetscInt Nv, Ns, Nc, i, sum_Nc = 0, deg = PETSC_MAX_INT, maxDeg = PETSC_MIN_INT;
259: PetscInt minNc, maxNc;
261: PetscFunctionBegin;
262: if (sum->setupCalled) PetscFunctionReturn(PETSC_SUCCESS);
264: PetscCall(PetscSpaceGetNumVariables(sp, &Nv));
265: PetscCall(PetscSpaceGetNumComponents(sp, &Nc));
266: PetscCall(PetscSpaceSumGetNumSubspaces(sp, &Ns));
267: if (Ns == PETSC_DEFAULT) {
268: Ns = 1;
269: PetscCall(PetscSpaceSumSetNumSubspaces(sp, Ns));
270: }
271: PetscCheck(Ns >= 0, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Cannot have %" PetscInt_FMT " subspaces", Ns);
272: uniform = PETSC_TRUE;
273: if (Ns) {
274: PetscSpace s0;
276: PetscCall(PetscSpaceSumGetSubspace(sp, 0, &s0));
277: for (PetscInt i = 1; i < Ns; i++) {
278: PetscSpace si;
280: PetscCall(PetscSpaceSumGetSubspace(sp, i, &si));
281: if (si != s0) {
282: uniform = PETSC_FALSE;
283: break;
284: }
285: }
286: }
288: minNc = Nc;
289: maxNc = Nc;
290: for (i = 0; i < Ns; ++i) {
291: PetscInt sNv, sNc, iDeg, iMaxDeg;
292: PetscSpace si;
294: PetscCall(PetscSpaceSumGetSubspace(sp, i, &si));
295: PetscCall(PetscSpaceSetUp(si));
296: PetscCall(PetscSpaceGetNumVariables(si, &sNv));
297: PetscCheck(sNv == Nv, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_WRONGSTATE, "Subspace %" PetscInt_FMT " has %" PetscInt_FMT " variables, space has %" PetscInt_FMT ".", i, sNv, Nv);
298: PetscCall(PetscSpaceGetNumComponents(si, &sNc));
299: if (i == 0 && sNc == Nc) concatenate = PETSC_FALSE;
300: minNc = PetscMin(minNc, sNc);
301: maxNc = PetscMax(maxNc, sNc);
302: sum_Nc += sNc;
303: PetscCall(PetscSpaceSumGetSubspace(sp, i, &si));
304: PetscCall(PetscSpaceGetDegree(si, &iDeg, &iMaxDeg));
305: deg = PetscMin(deg, iDeg);
306: maxDeg = PetscMax(maxDeg, iMaxDeg);
307: }
309: if (concatenate) PetscCheck(sum_Nc == Nc, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Total number of subspace components (%" PetscInt_FMT ") does not match number of target space components (%" PetscInt_FMT ").", sum_Nc, Nc);
310: else PetscCheck(minNc == Nc && maxNc == Nc, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Subspaces must have same number of components as the target space.");
312: sp->degree = deg;
313: sp->maxDegree = maxDeg;
314: sum->concatenate = concatenate;
315: sum->uniform = uniform;
316: sum->setupCalled = PETSC_TRUE;
317: PetscFunctionReturn(PETSC_SUCCESS);
318: }
320: static PetscErrorCode PetscSpaceSumView_Ascii(PetscSpace sp, PetscViewer v)
321: {
322: PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
323: PetscBool concatenate = sum->concatenate;
324: PetscInt i, Ns = sum->numSumSpaces;
326: PetscFunctionBegin;
327: if (concatenate) PetscCall(PetscViewerASCIIPrintf(v, "Sum space of %" PetscInt_FMT " concatenated subspaces%s\n", Ns, sum->uniform ? " (all identical)" : ""));
328: else PetscCall(PetscViewerASCIIPrintf(v, "Sum space of %" PetscInt_FMT " subspaces%s\n", Ns, sum->uniform ? " (all identical)" : ""));
329: for (i = 0; i < (sum->uniform ? (Ns > 0 ? 1 : 0) : Ns); ++i) {
330: PetscCall(PetscViewerASCIIPushTab(v));
331: PetscCall(PetscSpaceView(sum->sumspaces[i], v));
332: PetscCall(PetscViewerASCIIPopTab(v));
333: }
334: PetscFunctionReturn(PETSC_SUCCESS);
335: }
337: static PetscErrorCode PetscSpaceView_Sum(PetscSpace sp, PetscViewer viewer)
338: {
339: PetscBool iascii;
341: PetscFunctionBegin;
342: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
343: if (iascii) PetscCall(PetscSpaceSumView_Ascii(sp, viewer));
344: PetscFunctionReturn(PETSC_SUCCESS);
345: }
347: static PetscErrorCode PetscSpaceDestroy_Sum(PetscSpace sp)
348: {
349: PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
350: PetscInt i, Ns = sum->numSumSpaces;
352: PetscFunctionBegin;
353: for (i = 0; i < Ns; ++i) PetscCall(PetscSpaceDestroy(&sum->sumspaces[i]));
354: PetscCall(PetscFree(sum->sumspaces));
355: if (sum->heightsubspaces) {
356: PetscInt d;
358: /* sp->Nv is the spatial dimension, so it is equal to the number
359: * of subspaces on higher co-dimension points */
360: for (d = 0; d < sp->Nv; ++d) PetscCall(PetscSpaceDestroy(&sum->heightsubspaces[d]));
361: }
362: PetscCall(PetscFree(sum->heightsubspaces));
363: PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetSubspace_C", NULL));
364: PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetSubspace_C", NULL));
365: PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetNumSubspaces_C", NULL));
366: PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetNumSubspaces_C", NULL));
367: PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetConcatenate_C", NULL));
368: PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetConcatenate_C", NULL));
369: PetscCall(PetscFree(sum));
370: PetscFunctionReturn(PETSC_SUCCESS);
371: }
373: static PetscErrorCode PetscSpaceGetDimension_Sum(PetscSpace sp, PetscInt *dim)
374: {
375: PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
376: PetscInt i, d = 0, Ns = sum->numSumSpaces;
378: PetscFunctionBegin;
379: if (!sum->setupCalled) {
380: PetscCall(PetscSpaceSetUp(sp));
381: PetscCall(PetscSpaceGetDimension(sp, dim));
382: PetscFunctionReturn(PETSC_SUCCESS);
383: }
385: for (i = 0; i < Ns; ++i) {
386: PetscInt id;
388: PetscCall(PetscSpaceGetDimension(sum->sumspaces[i], &id));
389: d += id;
390: }
392: *dim = d;
393: PetscFunctionReturn(PETSC_SUCCESS);
394: }
396: static PetscErrorCode PetscSpaceEvaluate_Sum(PetscSpace sp, PetscInt npoints, const PetscReal points[], PetscReal B[], PetscReal D[], PetscReal H[])
397: {
398: PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
399: PetscBool concatenate = sum->concatenate;
400: DM dm = sp->dm;
401: PetscInt Nc = sp->Nc, Nv = sp->Nv, Ns = sum->numSumSpaces;
402: PetscInt i, s, offset, ncoffset, pdimfull, numelB, numelD, numelH;
403: PetscReal *sB = NULL, *sD = NULL, *sH = NULL;
405: PetscFunctionBegin;
406: if (!sum->setupCalled) {
407: PetscCall(PetscSpaceSetUp(sp));
408: PetscCall(PetscSpaceEvaluate(sp, npoints, points, B, D, H));
409: PetscFunctionReturn(PETSC_SUCCESS);
410: }
411: PetscCall(PetscSpaceGetDimension(sp, &pdimfull));
412: numelB = npoints * pdimfull * Nc;
413: numelD = numelB * Nv;
414: numelH = numelD * Nv;
415: if (B || D || H) PetscCall(DMGetWorkArray(dm, numelB, MPIU_REAL, &sB));
416: if (D || H) PetscCall(DMGetWorkArray(dm, numelD, MPIU_REAL, &sD));
417: if (H) PetscCall(DMGetWorkArray(dm, numelH, MPIU_REAL, &sH));
418: if (B)
419: for (i = 0; i < numelB; ++i) B[i] = 0.;
420: if (D)
421: for (i = 0; i < numelD; ++i) D[i] = 0.;
422: if (H)
423: for (i = 0; i < numelH; ++i) H[i] = 0.;
425: for (s = 0, offset = 0, ncoffset = 0; s < Ns; ++s) {
426: PetscInt sNv, spdim, sNc, p;
428: PetscCall(PetscSpaceGetNumVariables(sum->sumspaces[s], &sNv));
429: PetscCall(PetscSpaceGetNumComponents(sum->sumspaces[s], &sNc));
430: PetscCall(PetscSpaceGetDimension(sum->sumspaces[s], &spdim));
431: PetscCheck(offset + spdim <= pdimfull, PetscObjectComm((PetscObject)sp), PETSC_ERR_ARG_OUTOFRANGE, "Subspace dimensions exceed target space dimension.");
432: if (s == 0 || !sum->uniform) PetscCall(PetscSpaceEvaluate(sum->sumspaces[s], npoints, points, sB, sD, sH));
433: if (B || D || H) {
434: for (p = 0; p < npoints; ++p) {
435: PetscInt j;
437: for (j = 0; j < spdim; ++j) {
438: PetscInt c;
440: for (c = 0; c < sNc; ++c) {
441: PetscInt compoffset, BInd, sBInd;
443: compoffset = concatenate ? c + ncoffset : c;
444: BInd = (p * pdimfull + j + offset) * Nc + compoffset;
445: sBInd = (p * spdim + j) * sNc + c;
446: if (B) B[BInd] = sB[sBInd];
447: if (D || H) {
448: PetscInt v;
450: for (v = 0; v < Nv; ++v) {
451: PetscInt DInd, sDInd;
453: DInd = BInd * Nv + v;
454: sDInd = sBInd * Nv + v;
455: if (D) D[DInd] = sD[sDInd];
456: if (H) {
457: PetscInt v2;
459: for (v2 = 0; v2 < Nv; ++v2) {
460: PetscInt HInd, sHInd;
462: HInd = DInd * Nv + v2;
463: sHInd = sDInd * Nv + v2;
464: H[HInd] = sH[sHInd];
465: }
466: }
467: }
468: }
469: }
470: }
471: }
472: }
473: offset += spdim;
474: ncoffset += sNc;
475: }
477: if (H) PetscCall(DMRestoreWorkArray(dm, numelH, MPIU_REAL, &sH));
478: if (D || H) PetscCall(DMRestoreWorkArray(dm, numelD, MPIU_REAL, &sD));
479: if (B || D || H) PetscCall(DMRestoreWorkArray(dm, numelB, MPIU_REAL, &sB));
480: PetscFunctionReturn(PETSC_SUCCESS);
481: }
483: static PetscErrorCode PetscSpaceGetHeightSubspace_Sum(PetscSpace sp, PetscInt height, PetscSpace *subsp)
484: {
485: PetscSpace_Sum *sum = (PetscSpace_Sum *)sp->data;
486: PetscInt Nc, dim, order;
487: PetscBool tensor;
489: PetscFunctionBegin;
490: PetscCall(PetscSpaceGetNumComponents(sp, &Nc));
491: PetscCall(PetscSpaceGetNumVariables(sp, &dim));
492: PetscCall(PetscSpaceGetDegree(sp, &order, NULL));
493: PetscCall(PetscSpacePolynomialGetTensor(sp, &tensor));
494: PetscCheck(height <= dim && height >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Asked for space at height %" PetscInt_FMT " for dimension %" PetscInt_FMT " space", height, dim);
495: if (!sum->heightsubspaces) PetscCall(PetscCalloc1(dim, &sum->heightsubspaces));
496: if (height <= dim) {
497: if (!sum->heightsubspaces[height - 1]) {
498: PetscSpace sub;
499: const char *name;
501: PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)sp), &sub));
502: PetscCall(PetscObjectGetName((PetscObject)sp, &name));
503: PetscCall(PetscObjectSetName((PetscObject)sub, name));
504: PetscCall(PetscSpaceSetType(sub, PETSCSPACESUM));
505: PetscCall(PetscSpaceSumSetNumSubspaces(sub, sum->numSumSpaces));
506: PetscCall(PetscSpaceSumSetConcatenate(sub, sum->concatenate));
507: PetscCall(PetscSpaceSetNumComponents(sub, Nc));
508: PetscCall(PetscSpaceSetNumVariables(sub, dim - height));
509: for (PetscInt i = 0; i < sum->numSumSpaces; i++) {
510: PetscSpace subh;
512: PetscCall(PetscSpaceGetHeightSubspace(sum->sumspaces[i], height, &subh));
513: PetscCall(PetscSpaceSumSetSubspace(sub, i, subh));
514: }
515: PetscCall(PetscSpaceSetUp(sub));
516: sum->heightsubspaces[height - 1] = sub;
517: }
518: *subsp = sum->heightsubspaces[height - 1];
519: } else {
520: *subsp = NULL;
521: }
522: PetscFunctionReturn(PETSC_SUCCESS);
523: }
525: static PetscErrorCode PetscSpaceInitialize_Sum(PetscSpace sp)
526: {
527: PetscFunctionBegin;
528: sp->ops->setfromoptions = PetscSpaceSetFromOptions_Sum;
529: sp->ops->setup = PetscSpaceSetUp_Sum;
530: sp->ops->view = PetscSpaceView_Sum;
531: sp->ops->destroy = PetscSpaceDestroy_Sum;
532: sp->ops->getdimension = PetscSpaceGetDimension_Sum;
533: sp->ops->evaluate = PetscSpaceEvaluate_Sum;
534: sp->ops->getheightsubspace = PetscSpaceGetHeightSubspace_Sum;
536: PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetNumSubspaces_C", PetscSpaceSumGetNumSubspaces_Sum));
537: PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetNumSubspaces_C", PetscSpaceSumSetNumSubspaces_Sum));
538: PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetSubspace_C", PetscSpaceSumGetSubspace_Sum));
539: PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetSubspace_C", PetscSpaceSumSetSubspace_Sum));
540: PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumGetConcatenate_C", PetscSpaceSumGetConcatenate_Sum));
541: PetscCall(PetscObjectComposeFunction((PetscObject)sp, "PetscSpaceSumSetConcatenate_C", PetscSpaceSumSetConcatenate_Sum));
542: PetscFunctionReturn(PETSC_SUCCESS);
543: }
545: /*MC
546: PETSCSPACESUM = "sum" - A `PetscSpace` object that encapsulates a sum of subspaces.
547: That sum can either be direct or concatenate a concatenation. For example if A and B are spaces each with 2 components,
548: 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
549: same number of variables.
551: Level: intermediate
553: .seealso: `PetscSpace`, `PetscSpaceType`, `PetscSpaceCreate()`, `PetscSpaceSetType()`
554: M*/
555: PETSC_EXTERN PetscErrorCode PetscSpaceCreate_Sum(PetscSpace sp)
556: {
557: PetscSpace_Sum *sum;
559: PetscFunctionBegin;
561: PetscCall(PetscNew(&sum));
562: sum->numSumSpaces = PETSC_DEFAULT;
563: sp->data = sum;
564: PetscCall(PetscSpaceInitialize_Sum(sp));
565: PetscFunctionReturn(PETSC_SUCCESS);
566: }
568: PETSC_EXTERN PetscErrorCode PetscSpaceCreateSum(PetscInt numSubspaces, const PetscSpace subspaces[], PetscBool concatenate, PetscSpace *sumSpace)
569: {
570: PetscInt i, Nv, Nc = 0;
572: PetscFunctionBegin;
573: if (sumSpace) PetscCall(PetscSpaceDestroy(sumSpace));
574: PetscCall(PetscSpaceCreate(PetscObjectComm((PetscObject)subspaces[0]), sumSpace));
575: PetscCall(PetscSpaceSetType(*sumSpace, PETSCSPACESUM));
576: PetscCall(PetscSpaceSumSetNumSubspaces(*sumSpace, numSubspaces));
577: PetscCall(PetscSpaceSumSetConcatenate(*sumSpace, concatenate));
578: for (i = 0; i < numSubspaces; ++i) {
579: PetscInt sNc;
581: PetscCall(PetscSpaceSumSetSubspace(*sumSpace, i, subspaces[i]));
582: PetscCall(PetscSpaceGetNumComponents(subspaces[i], &sNc));
583: if (concatenate) Nc += sNc;
584: else Nc = sNc;
585: }
586: PetscCall(PetscSpaceGetNumVariables(subspaces[0], &Nv));
587: PetscCall(PetscSpaceSetNumComponents(*sumSpace, Nc));
588: PetscCall(PetscSpaceSetNumVariables(*sumSpace, Nv));
589: PetscCall(PetscSpaceSetUp(*sumSpace));
591: PetscFunctionReturn(PETSC_SUCCESS);
592: }