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: PetscSpaceSumSetNumSubspaces(), PetscSpaceSetDegree(), PetscSpaceSetNumVariables()
     14: @*/
     15: PetscErrorCode PetscSpaceSumGetNumSubspaces(PetscSpace sp,PetscInt *numSumSpaces)
     16: {
     19:   PetscTryMethod(sp,"PetscSpaceSumGetNumSubspaces_C",(PetscSpace,PetscInt*),(sp,numSumSpaces));
     20:   return 0;
     21: }

     23: /*@
     24:   PetscSpaceSumSetNumSubspaces - Set the number of spaces in the sum

     26:   Input Parameters:
     27: + sp  - the function space object
     28: - numSumSpaces - the number of spaces

     30: Level: intermediate

     32: .seealso: PetscSpaceSumGetNumSubspaces(), PetscSpaceSetDegree(), PetscSpaceSetNumVariables()
     33: @*/
     34: PetscErrorCode PetscSpaceSumSetNumSubspaces(PetscSpace sp,PetscInt numSumSpaces)
     35: {
     37:   PetscTryMethod(sp,"PetscSpaceSumSetNumSubspaces_C",(PetscSpace,PetscInt),(sp,numSumSpaces));
     38:   return 0;
     39: }

     41: /*@
     42:  PetscSpaceSumGetConcatenate - Get the concatenate flag for this space.
     43:  A concatenated sum space will have number of components equal to the sum of the number of components of all subspaces.A non-concatenated,
     44:  or direct sum space will have the same number of components as its subspaces .

     46:  Input Parameters:
     47: . sp - the function space object

     49:  Output Parameters:
     50: . concatenate - flag indicating whether subspaces are concatenated.

     52: Level: intermediate

     54: .seealso: PetscSpaceSumSetConcatenate()
     55: @*/
     56: PetscErrorCode PetscSpaceSumGetConcatenate(PetscSpace sp,PetscBool *concatenate)
     57: {
     59:   PetscTryMethod(sp,"PetscSpaceSumGetConcatenate_C",(PetscSpace,PetscBool*),(sp,concatenate));
     60:   return 0;
     61: }

     63: /*@
     64:   PetscSpaceSumSetConcatenate - Sets the concatenate flag for this space.
     65:  A concatenated sum space will have number of components equal to the sum of the number of components of all subspaces.A non-concatenated,
     66:  or direct sum space will have the same number of components as its subspaces .

     68:  Input Parameters:
     69: + sp - the function space object
     70: - concatenate - are subspaces concatenated components (true) or direct summands (false)

     72: Level: intermediate
     73: .seealso: PetscSpaceSumGetConcatenate()
     74: @*/
     75: PetscErrorCode PetscSpaceSumSetConcatenate(PetscSpace sp,PetscBool concatenate)
     76: {
     78:   PetscTryMethod(sp,"PetscSpaceSumSetConcatenate_C",(PetscSpace,PetscBool),(sp,concatenate));
     79:   return 0;
     80: }

     82: /*@
     83:   PetscSpaceSumGetSubspace - Get a space in the sum

     85:   Input Parameters:
     86: + sp - the function space object
     87: - s  - The space number

     89:   Output Parameter:
     90: . subsp - the PetscSpace

     92: Level: intermediate

     94: .seealso: PetscSpaceSumSetSubspace(), PetscSpaceSetDegree(), PetscSpaceSetNumVariables()
     95: @*/
     96: PetscErrorCode PetscSpaceSumGetSubspace(PetscSpace sp,PetscInt s,PetscSpace *subsp)
     97: {
    100:   PetscTryMethod(sp,"PetscSpaceSumGetSubspace_C",(PetscSpace,PetscInt,PetscSpace*),(sp,s,subsp));
    101:   return 0;
    102: }

    104: /*@
    105:   PetscSpaceSumSetSubspace - Set a space in the sum

    107:   Input Parameters:
    108: + sp    - the function space object
    109: . s     - The space number
    110: - subsp - the number of spaces

    112: Level: intermediate

    114: .seealso: PetscSpaceSumGetSubspace(), PetscSpaceSetDegree(), PetscSpaceSetNumVariables()
    115: @*/
    116: PetscErrorCode PetscSpaceSumSetSubspace(PetscSpace sp,PetscInt s,PetscSpace subsp)
    117: {
    120:   PetscTryMethod(sp,"PetscSpaceSumSetSubspace_C",(PetscSpace,PetscInt,PetscSpace),(sp,s,subsp));
    121:   return 0;
    122: }

    124: static PetscErrorCode PetscSpaceSumGetNumSubspaces_Sum(PetscSpace space,PetscInt *numSumSpaces)
    125: {
    126:   PetscSpace_Sum *sum = (PetscSpace_Sum*)space->data;

    128:   *numSumSpaces = sum->numSumSpaces;
    129:   return 0;
    130: }

    132: static PetscErrorCode PetscSpaceSumSetNumSubspaces_Sum(PetscSpace space,PetscInt numSumSpaces)
    133: {
    134:   PetscSpace_Sum *sum = (PetscSpace_Sum*)space->data;
    135:   PetscInt       Ns   = sum->numSumSpaces;

    138:   if (numSumSpaces == Ns) return 0;
    139:   if (Ns >= 0) {
    140:     PetscInt s;
    141:     for (s=0; s<Ns; ++s) {
    142:       PetscSpaceDestroy(&sum->sumspaces[s]);
    143:     }
    144:     PetscFree(sum->sumspaces);
    145:   }

    147:   Ns   = sum->numSumSpaces = numSumSpaces;
    148:   PetscCalloc1(Ns,&sum->sumspaces);
    149:   return 0;
    150: }

    152: static PetscErrorCode PetscSpaceSumGetConcatenate_Sum(PetscSpace sp,PetscBool *concatenate)
    153: {
    154:   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;

    156:   *concatenate = sum->concatenate;
    157:   return 0;
    158: }

    160: static PetscErrorCode PetscSpaceSumSetConcatenate_Sum(PetscSpace sp,PetscBool concatenate)
    161: {
    162:   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;

    166:   sum->concatenate = concatenate;
    167:   return 0;
    168: }

    170: static PetscErrorCode PetscSpaceSumGetSubspace_Sum(PetscSpace space,PetscInt s,PetscSpace *subspace)
    171: {
    172:   PetscSpace_Sum *sum = (PetscSpace_Sum*)space->data;
    173:   PetscInt       Ns   = sum->numSumSpaces;

    178:   *subspace = sum->sumspaces[s];
    179:   return 0;
    180: }

    182: static PetscErrorCode PetscSpaceSumSetSubspace_Sum(PetscSpace space,PetscInt s,PetscSpace subspace)
    183: {
    184:   PetscSpace_Sum *sum = (PetscSpace_Sum*)space->data;
    185:   PetscInt       Ns   = sum->numSumSpaces;

    191:   PetscObjectReference((PetscObject)subspace);
    192:   PetscSpaceDestroy(&sum->sumspaces[s]);
    193:   sum->sumspaces[s] = subspace;
    194:   return 0;
    195: }

    197: static PetscErrorCode PetscSpaceSetFromOptions_Sum(PetscOptionItems *PetscOptionsObject,PetscSpace sp)
    198: {
    199:   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
    200:   PetscInt       Ns,Nc,Nv,deg,i;
    201:   PetscBool      concatenate = PETSC_TRUE;
    202:   const char     *prefix;

    204:   PetscSpaceGetNumVariables(sp,&Nv);
    205:   if (!Nv) return 0;
    206:   PetscSpaceGetNumComponents(sp,&Nc);
    207:   PetscSpaceSumGetNumSubspaces(sp,&Ns);
    208:   PetscSpaceGetDegree(sp,&deg,NULL);
    209:   Ns   = (Ns == PETSC_DEFAULT) ? 1 : Ns;

    211:   PetscOptionsHead(PetscOptionsObject,"PetscSpace sum options");
    212:   PetscOptionsBoundedInt("-petscspace_sum_spaces","The number of subspaces","PetscSpaceSumSetNumSubspaces",Ns,&Ns,NULL,0);
    213:   PetscCall(PetscOptionsBool("-petscspace_sum_concatenate","Subspaces are concatenated components of the final space","PetscSpaceSumSetFromOptions",
    214:                            concatenate,&concatenate,NULL));
    215:   PetscOptionsTail();

    218:   if (Ns != sum->numSumSpaces) {
    219:     PetscSpaceSumSetNumSubspaces(sp,Ns);
    220:   }
    221:   PetscObjectGetOptionsPrefix((PetscObject)sp,&prefix);
    222:   for (i=0; i<Ns; ++i) {
    223:     PetscInt   sNv;
    224:     PetscSpace subspace;

    226:     PetscSpaceSumGetSubspace(sp,i,&subspace);
    227:     if (!subspace) {
    228:       char subspacePrefix[256];

    230:       PetscSpaceCreate(PetscObjectComm((PetscObject)sp),&subspace);
    231:       PetscObjectSetOptionsPrefix((PetscObject)subspace,prefix);
    232:       PetscSNPrintf(subspacePrefix,256,"sumcomp_%D_",i);
    233:       PetscObjectAppendOptionsPrefix((PetscObject)subspace,subspacePrefix);
    234:     } else {
    235:       PetscObjectReference((PetscObject)subspace);
    236:     }
    237:     PetscSpaceSetFromOptions(subspace);
    238:     PetscSpaceGetNumVariables(subspace,&sNv);
    240:     PetscSpaceSumSetSubspace(sp,i,subspace);
    241:     PetscSpaceDestroy(&subspace);
    242:   }
    243:   return 0;
    244: }

    246: static PetscErrorCode PetscSpaceSetUp_Sum(PetscSpace sp)
    247: {
    248:   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
    249:   PetscBool      concatenate = PETSC_TRUE;
    250:   PetscBool      uniform;
    251:   PetscInt       Nv,Ns,Nc,i,sum_Nc = 0,deg = PETSC_MAX_INT,maxDeg = PETSC_MIN_INT;
    252:   PetscInt       minNc,maxNc;

    254:   if (sum->setupCalled) return 0;

    256:   PetscSpaceGetNumVariables(sp,&Nv);
    257:   PetscSpaceGetNumComponents(sp,&Nc);
    258:   PetscSpaceSumGetNumSubspaces(sp,&Ns);
    259:   if (Ns == PETSC_DEFAULT) {
    260:     Ns   = 1;
    261:     PetscSpaceSumSetNumSubspaces(sp,Ns);
    262:   }
    264:   uniform = PETSC_TRUE;
    265:   if (Ns) {
    266:     PetscSpace s0;

    268:     PetscSpaceSumGetSubspace(sp,0,&s0);
    269:     for (PetscInt i = 1; i < Ns; i++) {
    270:       PetscSpace si;

    272:       PetscSpaceSumGetSubspace(sp,i,&si);
    273:       if (si != s0) {
    274:         uniform = PETSC_FALSE;
    275:         break;
    276:       }
    277:     }
    278:   }

    280:   minNc = Nc;
    281:   maxNc = Nc;
    282:   for (i=0; i<Ns; ++i) {
    283:     PetscInt   sNv,sNc,iDeg,iMaxDeg;
    284:     PetscSpace si;

    286:     PetscSpaceSumGetSubspace(sp,i,&si);
    287:     PetscSpaceSetUp(si);
    288:     PetscSpaceGetNumVariables(si,&sNv);
    290:     PetscSpaceGetNumComponents(si,&sNc);
    291:     if (i == 0 && sNc == Nc) concatenate = PETSC_FALSE;
    292:     minNc = PetscMin(minNc, sNc);
    293:     maxNc = PetscMax(maxNc, sNc);
    294:     sum_Nc += sNc;
    295:     PetscSpaceSumGetSubspace(sp,i,&si);
    296:     PetscSpaceGetDegree(si,&iDeg,&iMaxDeg);
    297:     deg     = PetscMin(deg,iDeg);
    298:     maxDeg  = PetscMax(maxDeg,iMaxDeg);
    299:   }

    301:   if (concatenate) {
    302:     if (sum_Nc != Nc) {
    303:       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);
    304:     }
    305:   } else {
    307:   }

    309:   sp->degree       = deg;
    310:   sp->maxDegree    = maxDeg;
    311:   sum->concatenate = concatenate;
    312:   sum->uniform     = uniform;
    313:   sum->setupCalled = PETSC_TRUE;
    314:   return 0;
    315: }

    317: static PetscErrorCode PetscSpaceSumView_Ascii(PetscSpace sp,PetscViewer v)
    318: {
    319:   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
    320:   PetscBool      concatenate = sum->concatenate;
    321:   PetscInt       i,Ns         = sum->numSumSpaces;

    323:   if (concatenate) {
    324:     PetscViewerASCIIPrintf(v,"Sum space of %D concatenated subspaces%s\n",Ns, sum->uniform ? " (all identical)": "");
    325:   } else {
    326:     PetscViewerASCIIPrintf(v,"Sum space of %D subspaces%s\n",Ns, sum->uniform ? " (all identical)" : "");
    327:   }
    328:   for (i=0; i < (sum->uniform ? (Ns > 0 ? 1 : 0) : Ns); ++i) {
    329:     PetscViewerASCIIPushTab(v);
    330:     PetscSpaceView(sum->sumspaces[i],v);
    331:     PetscViewerASCIIPopTab(v);
    332:   }
    333:   return 0;
    334: }

    336: static PetscErrorCode PetscSpaceView_Sum(PetscSpace sp,PetscViewer viewer)
    337: {
    338:   PetscBool      iascii;

    340:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
    341:   if (iascii) {
    342:     PetscSpaceSumView_Ascii(sp,viewer);
    343:   }
    344:   return 0;
    345: }

    347: static PetscErrorCode PetscSpaceDestroy_Sum(PetscSpace sp)
    348: {
    349:   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
    350:   PetscInt       i,Ns   = sum->numSumSpaces;

    352:   for (i=0; i<Ns; ++i) {
    353:     PetscSpaceDestroy(&sum->sumspaces[i]);
    354:   }
    355:   PetscFree(sum->sumspaces);
    356:   if (sum->heightsubspaces) {
    357:     PetscInt d;

    359:     /* sp->Nv is the spatial dimension, so it is equal to the number
    360:      * of subspaces on higher co-dimension points */
    361:     for (d = 0; d < sp->Nv; ++d) {
    362:       PetscSpaceDestroy(&sum->heightsubspaces[d]);
    363:     }
    364:   }
    365:   PetscFree(sum->heightsubspaces);
    366:   PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetSubspace_C",NULL);
    367:   PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetSubspace_C",NULL);
    368:   PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetNumSubspaces_C",NULL);
    369:   PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetNumSubspaces_C",NULL);
    370:   PetscFree(sum);
    371:   return 0;
    372: }

    374: static PetscErrorCode PetscSpaceGetDimension_Sum(PetscSpace sp,PetscInt *dim)
    375: {
    376:   PetscSpace_Sum *sum = (PetscSpace_Sum*)sp->data;
    377:   PetscInt       i,d = 0,Ns = sum->numSumSpaces;

    379:   if (!sum->setupCalled) {
    380:     PetscSpaceSetUp(sp);
    381:     PetscSpaceGetDimension(sp, dim);
    382:     return 0;
    383:   }

    385:   for (i=0; i<Ns; ++i) {
    386:     PetscInt id;

    388:     PetscSpaceGetDimension(sum->sumspaces[i],&id);
    389:     d   += id;
    390:   }

    392:   *dim = d;
    393:   return 0;
    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:   if (!sum->setupCalled) {
    406:     PetscSpaceSetUp(sp);
    407:     PetscSpaceEvaluate(sp, npoints, points, B, D, H);
    408:     return 0;
    409:   }
    410:   PetscSpaceGetDimension(sp,&pdimfull);
    411:   numelB = npoints*pdimfull*Nc;
    412:   numelD = numelB*Nv;
    413:   numelH = numelD*Nv;
    414:   if (B || D || H) {
    415:     DMGetWorkArray(dm,numelB,MPIU_REAL,&sB);
    416:   }
    417:   if (D || H) {
    418:     DMGetWorkArray(dm,numelD,MPIU_REAL,&sD);
    419:   }
    420:   if (H) {
    421:     DMGetWorkArray(dm,numelH,MPIU_REAL,&sH);
    422:   }
    423:   if (B)
    424:     for (i=0; i<numelB; ++i) B[i] = 0.;
    425:   if (D)
    426:     for (i=0; i<numelD; ++i) D[i] = 0.;
    427:   if (H)
    428:     for (i=0; i<numelH; ++i) H[i] = 0.;

    430:   for (s=0,offset=0,ncoffset=0; s<Ns; ++s) {
    431:     PetscInt sNv,spdim,sNc,p;

    433:     PetscSpaceGetNumVariables(sum->sumspaces[s],&sNv);
    434:     PetscSpaceGetNumComponents(sum->sumspaces[s],&sNc);
    435:     PetscSpaceGetDimension(sum->sumspaces[s],&spdim);
    437:     if (s == 0 || !sum->uniform) {
    438:       PetscSpaceEvaluate(sum->sumspaces[s],npoints,points,sB,sD,sH);
    439:     }
    440:     if (B || D || H) {
    441:       for (p=0; p<npoints; ++p) {
    442:         PetscInt j;

    444:         for (j=0; j<spdim; ++j) {
    445:           PetscInt c;

    447:           for (c=0; c<sNc; ++c) {
    448:             PetscInt compoffset,BInd,sBInd;

    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;

    457:               for (v=0; v<Nv; ++v) {
    458:                 PetscInt DInd,sDInd;

    460:                 DInd  = BInd*Nv + v;
    461:                 sDInd = sBInd*Nv + v;
    462:                 if (D) D[DInd] = sD[sDInd];
    463:                 if (H) {
    464:                   PetscInt v2;

    466:                   for (v2=0; v2<Nv; ++v2) {
    467:                     PetscInt HInd,sHInd;

    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:   }

    484:   if (H) {
    485:     DMRestoreWorkArray(dm,numelH,MPIU_REAL,&sH);
    486:   }
    487:   if (D || H) {
    488:     DMRestoreWorkArray(dm,numelD,MPIU_REAL,&sD);
    489:   }
    490:   if (B || D || H) {
    491:     DMRestoreWorkArray(dm,numelB,MPIU_REAL,&sB);
    492:   }
    493:   return 0;
    494: }

    496: static PetscErrorCode PetscSpaceGetHeightSubspace_Sum(PetscSpace sp, PetscInt height, PetscSpace *subsp)
    497: {
    498:   PetscSpace_Sum  *sum = (PetscSpace_Sum *) sp->data;
    499:   PetscInt         Nc, dim, order;
    500:   PetscBool        tensor;

    502:   PetscSpaceGetNumComponents(sp, &Nc);
    503:   PetscSpaceGetNumVariables(sp, &dim);
    504:   PetscSpaceGetDegree(sp, &order, NULL);
    505:   PetscSpacePolynomialGetTensor(sp, &tensor);
    507:   if (!sum->heightsubspaces) PetscCalloc1(dim, &sum->heightsubspaces);
    508:   if (height <= dim) {
    509:     if (!sum->heightsubspaces[height-1]) {
    510:       PetscSpace  sub;
    511:       const char *name;

    513:       PetscSpaceCreate(PetscObjectComm((PetscObject) sp), &sub);
    514:       PetscObjectGetName((PetscObject) sp,  &name);
    515:       PetscObjectSetName((PetscObject) sub,  name);
    516:       PetscSpaceSetType(sub, PETSCSPACESUM);
    517:       PetscSpaceSumSetNumSubspaces(sub, sum->numSumSpaces);
    518:       PetscSpaceSumSetConcatenate(sub, sum->concatenate);
    519:       PetscSpaceSetNumComponents(sub, Nc);
    520:       PetscSpaceSetNumVariables(sub, dim-height);
    521:       for (PetscInt i = 0; i < sum->numSumSpaces; i++) {
    522:         PetscSpace subh;

    524:         PetscSpaceGetHeightSubspace(sum->sumspaces[i], height, &subh);
    525:         PetscSpaceSumSetSubspace(sub, i, subh);
    526:       }
    527:       PetscSpaceSetUp(sub);
    528:       sum->heightsubspaces[height-1] = sub;
    529:     }
    530:     *subsp = sum->heightsubspaces[height-1];
    531:   } else {
    532:     *subsp = NULL;
    533:   }
    534:   return 0;
    535: }

    537: static PetscErrorCode PetscSpaceInitialize_Sum(PetscSpace sp)
    538: {
    539:   sp->ops->setfromoptions    = PetscSpaceSetFromOptions_Sum;
    540:   sp->ops->setup             = PetscSpaceSetUp_Sum;
    541:   sp->ops->view              = PetscSpaceView_Sum;
    542:   sp->ops->destroy           = PetscSpaceDestroy_Sum;
    543:   sp->ops->getdimension      = PetscSpaceGetDimension_Sum;
    544:   sp->ops->evaluate          = PetscSpaceEvaluate_Sum;
    545:   sp->ops->getheightsubspace = PetscSpaceGetHeightSubspace_Sum;

    547:   PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetNumSubspaces_C",PetscSpaceSumGetNumSubspaces_Sum);
    548:   PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetNumSubspaces_C",PetscSpaceSumSetNumSubspaces_Sum);
    549:   PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetSubspace_C",PetscSpaceSumGetSubspace_Sum);
    550:   PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetSubspace_C",PetscSpaceSumSetSubspace_Sum);
    551:   PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumGetConcatenate_C",PetscSpaceSumGetConcatenate_Sum);
    552:   PetscObjectComposeFunction((PetscObject)sp,"PetscSpaceSumSetConcatenate_C",PetscSpaceSumSetConcatenate_Sum);
    553:   return 0;
    554: }

    556: /*MC
    557:   PETSCSPACESUM = "sum" - A PetscSpace object that encapsulates a sum of subspaces.
    558:   That sum can either be direct or concatenate a concatenation.For example if A and B are spaces each with 2 components,
    559:   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
    560:   same number of variables.

    562: Level: intermediate

    564: .seealso: PetscSpaceType, PetscSpaceCreate(), PetscSpaceSetType()
    565: M*/
    566: PETSC_EXTERN PetscErrorCode PetscSpaceCreate_Sum(PetscSpace sp)
    567: {
    568:   PetscSpace_Sum *sum;

    571:   PetscNewLog(sp,&sum);
    572:   sum->numSumSpaces = PETSC_DEFAULT;
    573:   sp->data = sum;
    574:   PetscSpaceInitialize_Sum(sp);
    575:   return 0;
    576: }

    578: PETSC_EXTERN PetscErrorCode PetscSpaceCreateSum(PetscInt numSubspaces,const PetscSpace subspaces[],PetscBool concatenate,PetscSpace *sumSpace)
    579: {
    580:   PetscInt       i,Nv,Nc = 0;

    582:   if (sumSpace) {
    583:     PetscSpaceDestroy(sumSpace);
    584:   }
    585:   PetscSpaceCreate(PetscObjectComm((PetscObject)subspaces[0]),sumSpace);
    586:   PetscSpaceSetType(*sumSpace,PETSCSPACESUM);
    587:   PetscSpaceSumSetNumSubspaces(*sumSpace,numSubspaces);
    588:   PetscSpaceSumSetConcatenate(*sumSpace,concatenate);
    589:   for (i=0; i<numSubspaces; ++i) {
    590:     PetscInt sNc;

    592:     PetscSpaceSumSetSubspace(*sumSpace,i,subspaces[i]);
    593:     PetscSpaceGetNumComponents(subspaces[i],&sNc);
    594:     if (concatenate) Nc += sNc;
    595:     else Nc = sNc;
    596:   }
    597:   PetscSpaceGetNumVariables(subspaces[0],&Nv);
    598:   PetscSpaceSetNumComponents(*sumSpace,Nc);
    599:   PetscSpaceSetNumVariables(*sumSpace,Nv);
    600:   PetscSpaceSetUp(*sumSpace);

    602:   return 0;
    603: }