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, &deg, 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: }