Date: 2021-03-03T22:27:04+00:00

Actual source code: dtds.c
petsc-3.14.5 2021-03-03
Report Typos and Errors

      1: #include <petsc/private/petscdsimpl.h>

      3: PetscClassId PETSCDS_CLASSID = 0;

      5: PetscFunctionList PetscDSList              = NULL;
      6: PetscBool         PetscDSRegisterAllCalled = PETSC_FALSE;

      8: /* A PetscDS (Discrete System) encodes a set of equations posed in a discrete space, which represents a set of
      9:    nonlinear continuum equations. The equations can have multiple fields, each field having a different
     10:    discretization. In addition, different pieces of the domain can have different field combinations and equations.

     12:    The DS provides the user a description of the approximation space on any given cell. It also gives pointwise
     13:    functions representing the equations.

     15:    Each field is associated with a label, marking the cells on which it is supported. Note that a field can be
     16:    supported on the closure of a cell not in the label due to overlap of the boundary of neighboring cells. The DM
     17:    then creates a DS for each set of cells with identical approximation spaces. When assembling, the user asks for
     18:    the space associated with a given cell. DMPlex uses the labels associated with each DS in the default integration loop.
     19: */

     21: /*@C
     22:   PetscDSRegister - Adds a new PetscDS implementation

     24:   Not Collective

     26:   Input Parameters:
     27: + name        - The name of a new user-defined creation routine
     28: - create_func - The creation routine itself

     30:   Notes:
     31:   PetscDSRegister() may be called multiple times to add several user-defined PetscDSs

     33:   Sample usage:
     34: .vb
     35:     PetscDSRegister("my_ds", MyPetscDSCreate);
     36: .ve

     38:   Then, your PetscDS type can be chosen with the procedural interface via
     39: .vb
     40:     PetscDSCreate(MPI_Comm, PetscDS *);
     41:     PetscDSSetType(PetscDS, "my_ds");
     42: .ve
     43:    or at runtime via the option
     44: .vb
     45:     -petscds_type my_ds
     46: .ve

     48:   Level: advanced

     50:    Not available from Fortran

     52: .seealso: PetscDSRegisterAll(), PetscDSRegisterDestroy()

     54: @*/
     55: PetscErrorCode PetscDSRegister(const char sname[], PetscErrorCode (*function)(PetscDS))
     56: {

     60:   PetscFunctionListAdd(&PetscDSList, sname, function);
     61:   return(0);
     62: }

     64: /*@C
     65:   PetscDSSetType - Builds a particular PetscDS

     67:   Collective on prob

     69:   Input Parameters:
     70: + prob - The PetscDS object
     71: - name - The kind of system

     73:   Options Database Key:
     74: . -petscds_type <type> - Sets the PetscDS type; use -help for a list of available types

     76:   Level: intermediate

     78:    Not available from Fortran

     80: .seealso: PetscDSGetType(), PetscDSCreate()
     81: @*/
     82: PetscErrorCode PetscDSSetType(PetscDS prob, PetscDSType name)
     83: {
     84:   PetscErrorCode (*r)(PetscDS);
     85:   PetscBool      match;

     90:   PetscObjectTypeCompare((PetscObject) prob, name, &match);
     91:   if (match) return(0);

     93:   PetscDSRegisterAll();
     94:   PetscFunctionListFind(PetscDSList, name, &r);
     95:   if (!r) SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDS type: %s", name);

     97:   if (prob->ops->destroy) {
     98:     (*prob->ops->destroy)(prob);
     99:     prob->ops->destroy = NULL;
    100:   }
    101:   (*r)(prob);
    102:   PetscObjectChangeTypeName((PetscObject) prob, name);
    103:   return(0);
    104: }

    106: /*@C
    107:   PetscDSGetType - Gets the PetscDS type name (as a string) from the object.

    109:   Not Collective

    111:   Input Parameter:
    112: . prob  - The PetscDS

    114:   Output Parameter:
    115: . name - The PetscDS type name

    117:   Level: intermediate

    119:    Not available from Fortran

    121: .seealso: PetscDSSetType(), PetscDSCreate()
    122: @*/
    123: PetscErrorCode PetscDSGetType(PetscDS prob, PetscDSType *name)
    124: {

    130:   PetscDSRegisterAll();
    131:   *name = ((PetscObject) prob)->type_name;
    132:   return(0);
    133: }

    135: static PetscErrorCode PetscDSView_Ascii(PetscDS prob, PetscViewer viewer)
    136: {
    137:   PetscViewerFormat  format;
    138:   const PetscScalar *constants;
    139:   PetscInt           numConstants, f;
    140:   PetscErrorCode     ierr;

    143:   PetscViewerGetFormat(viewer, &format);
    144:   PetscViewerASCIIPrintf(viewer, "Discrete System with %d fields\n", prob->Nf);
    145:   PetscViewerASCIIPushTab(viewer);
    146:   PetscViewerASCIIPrintf(viewer, "  cell total dim %D total comp %D\n", prob->totDim, prob->totComp);
    147:   if (prob->isHybrid) {PetscViewerASCIIPrintf(viewer, "  hybrid cell\n");}
    148:   for (f = 0; f < prob->Nf; ++f) {
    149:     DSBoundary      b;
    150:     PetscObject     obj;
    151:     PetscClassId    id;
    152:     PetscQuadrature q;
    153:     const char     *name;
    154:     PetscInt        Nc, Nq, Nqc;

    156:     PetscDSGetDiscretization(prob, f, &obj);
    157:     PetscObjectGetClassId(obj, &id);
    158:     PetscObjectGetName(obj, &name);
    159:     PetscViewerASCIIPrintf(viewer, "Field %s", name ? name : "<unknown>");
    160:     PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);
    161:     if (id == PETSCFE_CLASSID)      {
    162:       PetscFEGetNumComponents((PetscFE) obj, &Nc);
    163:       PetscFEGetQuadrature((PetscFE) obj, &q);
    164:       PetscViewerASCIIPrintf(viewer, " FEM");
    165:     } else if (id == PETSCFV_CLASSID) {
    166:       PetscFVGetNumComponents((PetscFV) obj, &Nc);
    167:       PetscFVGetQuadrature((PetscFV) obj, &q);
    168:       PetscViewerASCIIPrintf(viewer, " FVM");
    169:     }
    170:     else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %D", f);
    171:     if (Nc > 1) {PetscViewerASCIIPrintf(viewer, "%D components", Nc);}
    172:     else        {PetscViewerASCIIPrintf(viewer, "%D component ", Nc);}
    173:     if (prob->implicit[f]) {PetscViewerASCIIPrintf(viewer, " (implicit)");}
    174:     else                   {PetscViewerASCIIPrintf(viewer, " (explicit)");}
    175:     if (q) {
    176:       PetscQuadratureGetData(q, NULL, &Nqc, &Nq, NULL, NULL);
    177:       PetscViewerASCIIPrintf(viewer, " (Nq %D Nqc %D)", Nq, Nqc);
    178:     }
    179:     PetscViewerASCIIPrintf(viewer, "\n");
    180:     PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);
    181:     PetscViewerASCIIPushTab(viewer);
    182:     if (id == PETSCFE_CLASSID)      {PetscFEView((PetscFE) obj, viewer);}
    183:     else if (id == PETSCFV_CLASSID) {PetscFVView((PetscFV) obj, viewer);}
    184:     PetscViewerASCIIPopTab(viewer);

    186:     for (b = prob->boundary; b; b = b->next) {
    187:       PetscInt c, i;

    189:       if (b->field != f) continue;
    190:       PetscViewerASCIIPushTab(viewer);
    191:       PetscViewerASCIIPrintf(viewer, "Boundary %s (%s) %s\n", b->name, b->labelname, DMBoundaryConditionTypes[b->type]);
    192:       if (!b->numcomps) {
    193:         PetscViewerASCIIPrintf(viewer, "  all components\n");
    194:       } else {
    195:         PetscViewerASCIIPrintf(viewer, "  components: ");
    196:         PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);
    197:         for (c = 0; c < b->numcomps; ++c) {
    198:           if (c > 0) {PetscViewerASCIIPrintf(viewer, ", ");}
    199:           PetscViewerASCIIPrintf(viewer, "%D", b->comps[c]);
    200:         }
    201:         PetscViewerASCIIPrintf(viewer, "\n");
    202:         PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);
    203:       }
    204:       PetscViewerASCIIPrintf(viewer, "  ids: ");
    205:       PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);
    206:       for (i = 0; i < b->numids; ++i) {
    207:         if (i > 0) {PetscViewerASCIIPrintf(viewer, ", ");}
    208:         PetscViewerASCIIPrintf(viewer, "%D", b->ids[i]);
    209:       }
    210:       PetscViewerASCIIPrintf(viewer, "\n");
    211:       PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);
    212:       PetscViewerASCIIPopTab(viewer);
    213:     }
    214:   }
    215:   PetscDSGetConstants(prob, &numConstants, &constants);
    216:   if (numConstants) {
    217:     PetscViewerASCIIPrintf(viewer, "%D constants\n", numConstants);
    218:     PetscViewerASCIIPushTab(viewer);
    219:     for (f = 0; f < numConstants; ++f) {PetscViewerASCIIPrintf(viewer, "%g\n", (double) PetscRealPart(constants[f]));}
    220:     PetscViewerASCIIPopTab(viewer);
    221:   }
    222:   PetscViewerASCIIPopTab(viewer);
    223:   return(0);
    224: }

    226: /*@C
    227:    PetscDSViewFromOptions - View from Options

    229:    Collective on PetscDS

    231:    Input Parameters:
    232: +  A - the PetscDS object
    233: .  obj - Optional object
    234: -  name - command line option

    236:    Level: intermediate
    237: .seealso:  PetscDS, PetscDSView, PetscObjectViewFromOptions(), PetscDSCreate()
    238: @*/
    239: PetscErrorCode  PetscDSViewFromOptions(PetscDS A,PetscObject obj,const char name[])
    240: {

    245:   PetscObjectViewFromOptions((PetscObject)A,obj,name);
    246:   return(0);
    247: }

    249: /*@C
    250:   PetscDSView - Views a PetscDS

    252:   Collective on prob

    254:   Input Parameter:
    255: + prob - the PetscDS object to view
    256: - v  - the viewer

    258:   Level: developer

    260: .seealso PetscDSDestroy()
    261: @*/
    262: PetscErrorCode PetscDSView(PetscDS prob, PetscViewer v)
    263: {
    264:   PetscBool      iascii;

    269:   if (!v) {PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) prob), &v);}
    271:   PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &iascii);
    272:   if (iascii) {PetscDSView_Ascii(prob, v);}
    273:   if (prob->ops->view) {(*prob->ops->view)(prob, v);}
    274:   return(0);
    275: }

    277: /*@
    278:   PetscDSSetFromOptions - sets parameters in a PetscDS from the options database

    280:   Collective on prob

    282:   Input Parameter:
    283: . prob - the PetscDS object to set options for

    285:   Options Database:
    286: + -petscds_type <type>     : Set the DS type
    287: . -petscds_view <view opt> : View the DS
    288: . -petscds_jac_pre         : Turn formation of a separate Jacobian preconditioner on and off
    289: . -bc_<name> <ids>         : Specify a list of label ids for a boundary condition
    290: - -bc_<name>_comp <comps>  : Specify a list of field components to constrain for a boundary condition

    292:   Level: developer

    294: .seealso PetscDSView()
    295: @*/
    296: PetscErrorCode PetscDSSetFromOptions(PetscDS prob)
    297: {
    298:   DSBoundary     b;
    299:   const char    *defaultType;
    300:   char           name[256];
    301:   PetscBool      flg;

    306:   if (!((PetscObject) prob)->type_name) {
    307:     defaultType = PETSCDSBASIC;
    308:   } else {
    309:     defaultType = ((PetscObject) prob)->type_name;
    310:   }
    311:   PetscDSRegisterAll();

    313:   PetscObjectOptionsBegin((PetscObject) prob);
    314:   for (b = prob->boundary; b; b = b->next) {
    315:     char       optname[1024];
    316:     PetscInt   ids[1024], len = 1024;
    317:     PetscBool  flg;

    319:     PetscSNPrintf(optname, sizeof(optname), "-bc_%s", b->name);
    320:     PetscMemzero(ids, sizeof(ids));
    321:     PetscOptionsIntArray(optname, "List of boundary IDs", "", ids, &len, &flg);
    322:     if (flg) {
    323:       b->numids = len;
    324:       PetscFree(b->ids);
    325:       PetscMalloc1(len, &b->ids);
    326:       PetscArraycpy(b->ids, ids, len);
    327:     }
    328:     len = 1024;
    329:     PetscSNPrintf(optname, sizeof(optname), "-bc_%s_comp", b->name);
    330:     PetscMemzero(ids, sizeof(ids));
    331:     PetscOptionsIntArray(optname, "List of boundary field components", "", ids, &len, &flg);
    332:     if (flg) {
    333:       b->numcomps = len;
    334:       PetscFree(b->comps);
    335:       PetscMalloc1(len, &b->comps);
    336:       PetscArraycpy(b->comps, ids, len);
    337:     }
    338:   }
    339:   PetscOptionsFList("-petscds_type", "Discrete System", "PetscDSSetType", PetscDSList, defaultType, name, 256, &flg);
    340:   if (flg) {
    341:     PetscDSSetType(prob, name);
    342:   } else if (!((PetscObject) prob)->type_name) {
    343:     PetscDSSetType(prob, defaultType);
    344:   }
    345:   PetscOptionsBool("-petscds_jac_pre", "Discrete System", "PetscDSUseJacobianPreconditioner", prob->useJacPre, &prob->useJacPre, &flg);
    346:   if (prob->ops->setfromoptions) {(*prob->ops->setfromoptions)(prob);}
    347:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
    348:   PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) prob);
    349:   PetscOptionsEnd();
    350:   if (prob->Nf) {PetscDSViewFromOptions(prob, NULL, "-petscds_view");}
    351:   return(0);
    352: }

    354: /*@C
    355:   PetscDSSetUp - Construct data structures for the PetscDS

    357:   Collective on prob

    359:   Input Parameter:
    360: . prob - the PetscDS object to setup

    362:   Level: developer

    364: .seealso PetscDSView(), PetscDSDestroy()
    365: @*/
    366: PetscErrorCode PetscDSSetUp(PetscDS prob)
    367: {
    368:   const PetscInt Nf = prob->Nf;
    369:   PetscInt       dim, dimEmbed, NbMax = 0, NcMax = 0, NqMax = 0, NsMax = 1, f;

    374:   if (prob->setup) return(0);
    375:   /* Calculate sizes */
    376:   PetscDSGetSpatialDimension(prob, &dim);
    377:   PetscDSGetCoordinateDimension(prob, &dimEmbed);
    378:   prob->totDim = prob->totComp = 0;
    379:   PetscMalloc2(Nf,&prob->Nc,Nf,&prob->Nb);
    380:   PetscCalloc2(Nf+1,&prob->off,Nf+1,&prob->offDer);
    381:   PetscMalloc2(Nf,&prob->T,Nf,&prob->Tf);
    382:   for (f = 0; f < Nf; ++f) {
    383:     PetscObject     obj;
    384:     PetscClassId    id;
    385:     PetscQuadrature q = NULL;
    386:     PetscInt        Nq = 0, Nb, Nc;

    388:     PetscDSGetDiscretization(prob, f, &obj);
    389:     if (!obj) {
    390:       /* Empty mesh */
    391:       Nb = Nc = 0;
    392:       prob->T[f] = prob->Tf[f] = NULL;
    393:     } else {
    394:       PetscObjectGetClassId(obj, &id);
    395:       if (id == PETSCFE_CLASSID)      {
    396:         PetscFE fe = (PetscFE) obj;

    398:         PetscFEGetQuadrature(fe, &q);
    399:         PetscFEGetDimension(fe, &Nb);
    400:         PetscFEGetNumComponents(fe, &Nc);
    401:         PetscFEGetCellTabulation(fe, &prob->T[f]);
    402:         PetscFEGetFaceTabulation(fe, &prob->Tf[f]);
    403:       } else if (id == PETSCFV_CLASSID) {
    404:         PetscFV fv = (PetscFV) obj;

    406:         PetscFVGetQuadrature(fv, &q);
    407:         PetscFVGetNumComponents(fv, &Nc);
    408:         Nb   = Nc;
    409:         PetscFVGetCellTabulation(fv, &prob->T[f]);
    410:         /* TODO: should PetscFV also have face tabulation? Otherwise there will be a null pointer in prob->basisFace */
    411:       } else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f);
    412:     }
    413:     prob->Nc[f]       = Nc;
    414:     prob->Nb[f]       = Nb;
    415:     prob->off[f+1]    = Nc     + prob->off[f];
    416:     prob->offDer[f+1] = Nc*dim + prob->offDer[f];
    417:     if (q) {PetscQuadratureGetData(q, NULL, NULL, &Nq, NULL, NULL);}
    418:     NqMax          = PetscMax(NqMax, Nq);
    419:     NbMax          = PetscMax(NbMax, Nb);
    420:     NcMax          = PetscMax(NcMax, Nc);
    421:     prob->totDim  += Nb;
    422:     prob->totComp += Nc;
    423:     /* There are two faces for all fields but the cohesive field on a hybrid cell */
    424:     if (prob->isHybrid && (f < Nf-1)) prob->totDim += Nb;
    425:   }
    426:   /* Allocate works space */
    427:   if (prob->isHybrid) NsMax = 2;
    428:   PetscMalloc3(NsMax*prob->totComp,&prob->u,NsMax*prob->totComp,&prob->u_t,NsMax*prob->totComp*dimEmbed,&prob->u_x);
    429:   PetscMalloc5(dimEmbed,&prob->x,NbMax*NcMax,&prob->basisReal,NbMax*NcMax*dimEmbed,&prob->basisDerReal,NbMax*NcMax,&prob->testReal,NbMax*NcMax*dimEmbed,&prob->testDerReal);
    430:   PetscMalloc6(NsMax*NqMax*NcMax,&prob->f0,NsMax*NqMax*NcMax*dimEmbed,&prob->f1,
    431:                       NsMax*NsMax*NqMax*NcMax*NcMax,&prob->g0,NsMax*NsMax*NqMax*NcMax*NcMax*dimEmbed,&prob->g1,
    432:                       NsMax*NsMax*NqMax*NcMax*NcMax*dimEmbed,&prob->g2,NsMax*NsMax*NqMax*NcMax*NcMax*dimEmbed*dimEmbed,&prob->g3);
    433:   if (prob->ops->setup) {(*prob->ops->setup)(prob);}
    434:   prob->setup = PETSC_TRUE;
    435:   return(0);
    436: }

    438: static PetscErrorCode PetscDSDestroyStructs_Static(PetscDS prob)
    439: {

    443:   PetscFree2(prob->Nc,prob->Nb);
    444:   PetscFree2(prob->off,prob->offDer);
    445:   PetscFree2(prob->T,prob->Tf);
    446:   PetscFree3(prob->u,prob->u_t,prob->u_x);
    447:   PetscFree5(prob->x,prob->basisReal, prob->basisDerReal,prob->testReal,prob->testDerReal);
    448:   PetscFree6(prob->f0,prob->f1,prob->g0,prob->g1,prob->g2,prob->g3);
    449:   return(0);
    450: }

    452: static PetscErrorCode PetscDSEnlarge_Static(PetscDS prob, PetscInt NfNew)
    453: {
    454:   PetscObject      *tmpd;
    455:   PetscBool        *tmpi;
    456:   PetscPointFunc   *tmpobj, *tmpf, *tmpup;
    457:   PetscPointJac    *tmpg, *tmpgp, *tmpgt;
    458:   PetscBdPointFunc *tmpfbd;
    459:   PetscBdPointJac  *tmpgbd, *tmpgpbd;
    460:   PetscRiemannFunc *tmpr;
    461:   PetscSimplePointFunc *tmpexactSol,  *tmpexactSol_t;
    462:   void                **tmpexactCtx, **tmpexactCtx_t;
    463:   void            **tmpctx;
    464:   PetscInt          Nf = prob->Nf, f;
    465:   PetscErrorCode    ierr;

    468:   if (Nf >= NfNew) return(0);
    469:   prob->setup = PETSC_FALSE;
    470:   PetscDSDestroyStructs_Static(prob);
    471:   PetscMalloc2(NfNew, &tmpd, NfNew, &tmpi);
    472:   for (f = 0; f < Nf; ++f) {tmpd[f] = prob->disc[f]; tmpi[f] = prob->implicit[f];}
    473:   for (f = Nf; f < NfNew; ++f) {tmpd[f] = NULL; tmpi[f] = PETSC_TRUE;}
    474:   PetscFree2(prob->disc, prob->implicit);
    475:   prob->Nf        = NfNew;
    476:   prob->disc      = tmpd;
    477:   prob->implicit  = tmpi;
    478:   PetscCalloc7(NfNew, &tmpobj, NfNew*2, &tmpf, NfNew*NfNew*4, &tmpg, NfNew*NfNew*4, &tmpgp, NfNew*NfNew*4, &tmpgt, NfNew, &tmpr, NfNew, &tmpctx);
    479:   PetscCalloc1(NfNew, &tmpup);
    480:   for (f = 0; f < Nf; ++f) tmpobj[f] = prob->obj[f];
    481:   for (f = 0; f < Nf*2; ++f) tmpf[f] = prob->f[f];
    482:   for (f = 0; f < Nf*Nf*4; ++f) tmpg[f] = prob->g[f];
    483:   for (f = 0; f < Nf*Nf*4; ++f) tmpgp[f] = prob->gp[f];
    484:   for (f = 0; f < Nf; ++f) tmpr[f] = prob->r[f];
    485:   for (f = 0; f < Nf; ++f) tmpup[f] = prob->update[f];
    486:   for (f = 0; f < Nf; ++f) tmpctx[f] = prob->ctx[f];
    487:   for (f = Nf; f < NfNew; ++f) tmpobj[f] = NULL;
    488:   for (f = Nf*2; f < NfNew*2; ++f) tmpf[f] = NULL;
    489:   for (f = Nf*Nf*4; f < NfNew*NfNew*4; ++f) tmpg[f] = NULL;
    490:   for (f = Nf*Nf*4; f < NfNew*NfNew*4; ++f) tmpgp[f] = NULL;
    491:   for (f = Nf*Nf*4; f < NfNew*NfNew*4; ++f) tmpgt[f] = NULL;
    492:   for (f = Nf; f < NfNew; ++f) tmpr[f] = NULL;
    493:   for (f = Nf; f < NfNew; ++f) tmpup[f] = NULL;
    494:   for (f = Nf; f < NfNew; ++f) tmpctx[f] = NULL;
    495:   PetscFree7(prob->obj, prob->f, prob->g, prob->gp, prob->gt, prob->r, prob->ctx);
    496:   PetscFree(prob->update);
    497:   prob->obj = tmpobj;
    498:   prob->f   = tmpf;
    499:   prob->g   = tmpg;
    500:   prob->gp  = tmpgp;
    501:   prob->gt  = tmpgt;
    502:   prob->r   = tmpr;
    503:   prob->update = tmpup;
    504:   prob->ctx = tmpctx;
    505:   PetscCalloc7(NfNew*2, &tmpfbd, NfNew*NfNew*4, &tmpgbd, NfNew*NfNew*4, &tmpgpbd, NfNew, &tmpexactSol, NfNew, &tmpexactCtx, NfNew, &tmpexactSol_t, NfNew, &tmpexactCtx_t);
    506:   for (f = 0; f < Nf*2; ++f) tmpfbd[f] = prob->fBd[f];
    507:   for (f = 0; f < Nf*Nf*4; ++f) tmpgbd[f] = prob->gBd[f];
    508:   for (f = 0; f < Nf*Nf*4; ++f) tmpgpbd[f] = prob->gpBd[f];
    509:   for (f = 0; f < Nf; ++f) tmpexactSol[f] = prob->exactSol[f];
    510:   for (f = 0; f < Nf; ++f) tmpexactCtx[f] = prob->exactCtx[f];
    511:   for (f = 0; f < Nf; ++f) tmpexactSol_t[f] = prob->exactSol_t[f];
    512:   for (f = 0; f < Nf; ++f) tmpexactCtx_t[f] = prob->exactCtx_t[f];
    513:   for (f = Nf*2; f < NfNew*2; ++f) tmpfbd[f] = NULL;
    514:   for (f = Nf*Nf*4; f < NfNew*NfNew*4; ++f) tmpgbd[f] = NULL;
    515:   for (f = Nf*Nf*4; f < NfNew*NfNew*4; ++f) tmpgpbd[f] = NULL;
    516:   for (f = Nf; f < NfNew; ++f) tmpexactSol[f] = NULL;
    517:   for (f = Nf; f < NfNew; ++f) tmpexactCtx[f] = NULL;
    518:   for (f = Nf; f < NfNew; ++f) tmpexactSol_t[f] = NULL;
    519:   for (f = Nf; f < NfNew; ++f) tmpexactCtx_t[f] = NULL;
    520:   PetscFree7(prob->fBd, prob->gBd, prob->gpBd, prob->exactSol, prob->exactCtx, prob->exactSol_t, prob->exactCtx_t);
    521:   prob->fBd = tmpfbd;
    522:   prob->gBd = tmpgbd;
    523:   prob->gpBd = tmpgpbd;
    524:   prob->exactSol = tmpexactSol;
    525:   prob->exactCtx = tmpexactCtx;
    526:   prob->exactSol_t = tmpexactSol_t;
    527:   prob->exactCtx_t = tmpexactCtx_t;
    528:   return(0);
    529: }

    531: /*@
    532:   PetscDSDestroy - Destroys a PetscDS object

    534:   Collective on prob

    536:   Input Parameter:
    537: . prob - the PetscDS object to destroy

    539:   Level: developer

    541: .seealso PetscDSView()
    542: @*/
    543: PetscErrorCode PetscDSDestroy(PetscDS *prob)
    544: {
    545:   PetscInt       f;
    546:   DSBoundary     next;

    550:   if (!*prob) return(0);

    553:   if (--((PetscObject)(*prob))->refct > 0) {*prob = NULL; return(0);}
    554:   ((PetscObject) (*prob))->refct = 0;
    555:   if ((*prob)->subprobs) {
    556:     PetscInt dim, d;

    558:     PetscDSGetSpatialDimension(*prob, &dim);
    559:     for (d = 0; d < dim; ++d) {PetscDSDestroy(&(*prob)->subprobs[d]);}
    560:   }
    561:   PetscFree((*prob)->subprobs);
    562:   PetscDSDestroyStructs_Static(*prob);
    563:   for (f = 0; f < (*prob)->Nf; ++f) {
    564:     PetscObjectDereference((*prob)->disc[f]);
    565:   }
    566:   PetscFree2((*prob)->disc, (*prob)->implicit);
    567:   PetscFree7((*prob)->obj,(*prob)->f,(*prob)->g,(*prob)->gp,(*prob)->gt,(*prob)->r,(*prob)->ctx);
    568:   PetscFree((*prob)->update);
    569:   PetscFree7((*prob)->fBd,(*prob)->gBd,(*prob)->gpBd,(*prob)->exactSol,(*prob)->exactCtx,(*prob)->exactSol_t,(*prob)->exactCtx_t);
    570:   if ((*prob)->ops->destroy) {(*(*prob)->ops->destroy)(*prob);}
    571:   next = (*prob)->boundary;
    572:   while (next) {
    573:     DSBoundary b = next;

    575:     next = b->next;
    576:     PetscFree(b->comps);
    577:     PetscFree(b->ids);
    578:     PetscFree(b->name);
    579:     PetscFree(b->labelname);
    580:     PetscFree(b);
    581:   }
    582:   PetscFree((*prob)->constants);
    583:   PetscHeaderDestroy(prob);
    584:   return(0);
    585: }

    587: /*@
    588:   PetscDSCreate - Creates an empty PetscDS object. The type can then be set with PetscDSSetType().

    590:   Collective

    592:   Input Parameter:
    593: . comm - The communicator for the PetscDS object

    595:   Output Parameter:
    596: . prob - The PetscDS object

    598:   Level: beginner

    600: .seealso: PetscDSSetType(), PETSCDSBASIC
    601: @*/
    602: PetscErrorCode PetscDSCreate(MPI_Comm comm, PetscDS *prob)
    603: {
    604:   PetscDS   p;

    609:   *prob  = NULL;
    610:   PetscDSInitializePackage();

    612:   PetscHeaderCreate(p, PETSCDS_CLASSID, "PetscDS", "Discrete System", "PetscDS", comm, PetscDSDestroy, PetscDSView);

    614:   p->Nf           = 0;
    615:   p->setup        = PETSC_FALSE;
    616:   p->numConstants = 0;
    617:   p->constants    = NULL;
    618:   p->dimEmbed     = -1;
    619:   p->useJacPre    = PETSC_TRUE;

    621:   *prob = p;
    622:   return(0);
    623: }

    625: /*@
    626:   PetscDSGetNumFields - Returns the number of fields in the DS

    628:   Not collective

    630:   Input Parameter:
    631: . prob - The PetscDS object

    633:   Output Parameter:
    634: . Nf - The number of fields

    636:   Level: beginner

    638: .seealso: PetscDSGetSpatialDimension(), PetscDSCreate()
    639: @*/
    640: PetscErrorCode PetscDSGetNumFields(PetscDS prob, PetscInt *Nf)
    641: {
    645:   *Nf = prob->Nf;
    646:   return(0);
    647: }

    649: /*@
    650:   PetscDSGetSpatialDimension - Returns the spatial dimension of the DS, meaning the topological dimension of the discretizations

    652:   Not collective

    654:   Input Parameter:
    655: . prob - The PetscDS object

    657:   Output Parameter:
    658: . dim - The spatial dimension

    660:   Level: beginner

    662: .seealso: PetscDSGetCoordinateDimension(), PetscDSGetNumFields(), PetscDSCreate()
    663: @*/
    664: PetscErrorCode PetscDSGetSpatialDimension(PetscDS prob, PetscInt *dim)
    665: {

    671:   *dim = 0;
    672:   if (prob->Nf) {
    673:     PetscObject  obj;
    674:     PetscClassId id;

    676:     PetscDSGetDiscretization(prob, 0, &obj);
    677:     if (obj) {
    678:       PetscObjectGetClassId(obj, &id);
    679:       if (id == PETSCFE_CLASSID)      {PetscFEGetSpatialDimension((PetscFE) obj, dim);}
    680:       else if (id == PETSCFV_CLASSID) {PetscFVGetSpatialDimension((PetscFV) obj, dim);}
    681:       else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
    682:     }
    683:   }
    684:   return(0);
    685: }

    687: /*@
    688:   PetscDSGetCoordinateDimension - Returns the coordinate dimension of the DS, meaning the dimension of the space into which the discretiaztions are embedded

    690:   Not collective

    692:   Input Parameter:
    693: . prob - The PetscDS object

    695:   Output Parameter:
    696: . dimEmbed - The coordinate dimension

    698:   Level: beginner

    700: .seealso: PetscDSSetCoordinateDimension(), PetscDSGetSpatialDimension(), PetscDSGetNumFields(), PetscDSCreate()
    701: @*/
    702: PetscErrorCode PetscDSGetCoordinateDimension(PetscDS prob, PetscInt *dimEmbed)
    703: {
    707:   if (prob->dimEmbed < 0) SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONGSTATE, "No coordinate dimension set for this DS");
    708:   *dimEmbed = prob->dimEmbed;
    709:   return(0);
    710: }

    712: /*@
    713:   PetscDSSetCoordinateDimension - Set the coordinate dimension of the DS, meaning the dimension of the space into which the discretiaztions are embedded

    715:   Logically collective on prob

    717:   Input Parameters:
    718: + prob - The PetscDS object
    719: - dimEmbed - The coordinate dimension

    721:   Level: beginner

    723: .seealso: PetscDSGetCoordinateDimension(), PetscDSGetSpatialDimension(), PetscDSGetNumFields(), PetscDSCreate()
    724: @*/
    725: PetscErrorCode PetscDSSetCoordinateDimension(PetscDS prob, PetscInt dimEmbed)
    726: {
    729:   if (dimEmbed < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate dimension must be non-negative, not %D", dimEmbed);
    730:   prob->dimEmbed = dimEmbed;
    731:   return(0);
    732: }

    734: /*@
    735:   PetscDSGetHybrid - Returns the flag for a hybrid (cohesive) cell

    737:   Not collective

    739:   Input Parameter:
    740: . prob - The PetscDS object

    742:   Output Parameter:
    743: . isHybrid - The flag

    745:   Level: developer

    747: .seealso: PetscDSSetHybrid(), PetscDSCreate()
    748: @*/
    749: PetscErrorCode PetscDSGetHybrid(PetscDS prob, PetscBool *isHybrid)
    750: {
    754:   *isHybrid = prob->isHybrid;
    755:   return(0);
    756: }

    758: /*@
    759:   PetscDSSetHybrid - Set the flag for a hybrid (cohesive) cell

    761:   Not collective

    763:   Input Parameters:
    764: + prob - The PetscDS object
    765: - isHybrid - The flag

    767:   Level: developer

    769: .seealso: PetscDSGetHybrid(), PetscDSCreate()
    770: @*/
    771: PetscErrorCode PetscDSSetHybrid(PetscDS prob, PetscBool isHybrid)
    772: {
    775:   prob->isHybrid = isHybrid;
    776:   return(0);
    777: }

    779: /*@
    780:   PetscDSGetTotalDimension - Returns the total size of the approximation space for this system

    782:   Not collective

    784:   Input Parameter:
    785: . prob - The PetscDS object

    787:   Output Parameter:
    788: . dim - The total problem dimension

    790:   Level: beginner

    792: .seealso: PetscDSGetNumFields(), PetscDSCreate()
    793: @*/
    794: PetscErrorCode PetscDSGetTotalDimension(PetscDS prob, PetscInt *dim)
    795: {

    800:   PetscDSSetUp(prob);
    802:   *dim = prob->totDim;
    803:   return(0);
    804: }

    806: /*@
    807:   PetscDSGetTotalComponents - Returns the total number of components in this system

    809:   Not collective

    811:   Input Parameter:
    812: . prob - The PetscDS object

    814:   Output Parameter:
    815: . dim - The total number of components

    817:   Level: beginner

    819: .seealso: PetscDSGetNumFields(), PetscDSCreate()
    820: @*/
    821: PetscErrorCode PetscDSGetTotalComponents(PetscDS prob, PetscInt *Nc)
    822: {

    827:   PetscDSSetUp(prob);
    829:   *Nc = prob->totComp;
    830:   return(0);
    831: }

    833: /*@
    834:   PetscDSGetDiscretization - Returns the discretization object for the given field

    836:   Not collective

    838:   Input Parameters:
    839: + prob - The PetscDS object
    840: - f - The field number

    842:   Output Parameter:
    843: . disc - The discretization object

    845:   Level: beginner

    847: .seealso: PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    848: @*/
    849: PetscErrorCode PetscDSGetDiscretization(PetscDS prob, PetscInt f, PetscObject *disc)
    850: {
    854:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    855:   *disc = prob->disc[f];
    856:   return(0);
    857: }

    859: /*@
    860:   PetscDSSetDiscretization - Sets the discretization object for the given field

    862:   Not collective

    864:   Input Parameters:
    865: + prob - The PetscDS object
    866: . f - The field number
    867: - disc - The discretization object

    869:   Level: beginner

    871: .seealso: PetscDSGetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    872: @*/
    873: PetscErrorCode PetscDSSetDiscretization(PetscDS prob, PetscInt f, PetscObject disc)
    874: {

    880:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    881:   PetscDSEnlarge_Static(prob, f+1);
    882:   PetscObjectDereference(prob->disc[f]);
    883:   prob->disc[f] = disc;
    884:   PetscObjectReference(disc);
    885:   if (disc) {
    886:     PetscClassId id;

    888:     PetscObjectGetClassId(disc, &id);
    889:     if (id == PETSCFE_CLASSID) {
    890:       PetscDSSetImplicit(prob, f, PETSC_TRUE);
    891:     } else if (id == PETSCFV_CLASSID) {
    892:       PetscDSSetImplicit(prob, f, PETSC_FALSE);
    893:     }
    894:   }
    895:   return(0);
    896: }

    898: /*@
    899:   PetscDSAddDiscretization - Adds a discretization object

    901:   Not collective

    903:   Input Parameters:
    904: + prob - The PetscDS object
    905: - disc - The boundary discretization object

    907:   Level: beginner

    909: .seealso: PetscDSGetDiscretization(), PetscDSSetDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    910: @*/
    911: PetscErrorCode PetscDSAddDiscretization(PetscDS prob, PetscObject disc)
    912: {

    916:   PetscDSSetDiscretization(prob, prob->Nf, disc);
    917:   return(0);
    918: }

    920: /*@
    921:   PetscDSGetQuadrature - Returns the quadrature, which must agree for all fields in the DS

    923:   Not collective

    925:   Input Parameter:
    926: . prob - The PetscDS object

    928:   Output Parameter:
    929: . q - The quadrature object

    931: Level: intermediate

    933: .seealso: PetscDSSetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    934: @*/
    935: PetscErrorCode PetscDSGetQuadrature(PetscDS prob, PetscQuadrature *q)
    936: {
    937:   PetscObject    obj;
    938:   PetscClassId   id;

    942:   *q = NULL;
    943:   if (!prob->Nf) return(0);
    944:   PetscDSGetDiscretization(prob, 0, &obj);
    945:   PetscObjectGetClassId(obj, &id);
    946:   if      (id == PETSCFE_CLASSID) {PetscFEGetQuadrature((PetscFE) obj, q);}
    947:   else if (id == PETSCFV_CLASSID) {PetscFVGetQuadrature((PetscFV) obj, q);}
    948:   else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
    949:   return(0);
    950: }

    952: /*@
    953:   PetscDSGetImplicit - Returns the flag for implicit solve for this field. This is just a guide for IMEX

    955:   Not collective

    957:   Input Parameters:
    958: + prob - The PetscDS object
    959: - f - The field number

    961:   Output Parameter:
    962: . implicit - The flag indicating what kind of solve to use for this field

    964:   Level: developer

    966: .seealso: PetscDSSetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    967: @*/
    968: PetscErrorCode PetscDSGetImplicit(PetscDS prob, PetscInt f, PetscBool *implicit)
    969: {
    973:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    974:   *implicit = prob->implicit[f];
    975:   return(0);
    976: }

    978: /*@
    979:   PetscDSSetImplicit - Set the flag for implicit solve for this field. This is just a guide for IMEX

    981:   Not collective

    983:   Input Parameters:
    984: + prob - The PetscDS object
    985: . f - The field number
    986: - implicit - The flag indicating what kind of solve to use for this field

    988:   Level: developer

    990: .seealso: PetscDSGetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    991: @*/
    992: PetscErrorCode PetscDSSetImplicit(PetscDS prob, PetscInt f, PetscBool implicit)
    993: {
    996:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    997:   prob->implicit[f] = implicit;
    998:   return(0);
    999: }

    1001: PetscErrorCode PetscDSGetObjective(PetscDS prob, PetscInt f,
    1002:                                    void (**obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1003:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1004:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1005:                                                 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]))
    1006: {
    1010:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    1011:   *obj = prob->obj[f];
    1012:   return(0);
    1013: }

    1015: PetscErrorCode PetscDSSetObjective(PetscDS prob, PetscInt f,
    1016:                                    void (*obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1017:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1018:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1019:                                                PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]))
    1020: {

    1026:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    1027:   PetscDSEnlarge_Static(prob, f+1);
    1028:   prob->obj[f] = obj;
    1029:   return(0);
    1030: }

    1032: /*@C
    1033:   PetscDSGetResidual - Get the pointwise residual function for a given test field

    1035:   Not collective

    1037:   Input Parameters:
    1038: + prob - The PetscDS
    1039: - f    - The test field number

    1041:   Output Parameters:
    1042: + f0 - integrand for the test function term
    1043: - f1 - integrand for the test function gradient term

    1045:   Note: We are using a first order FEM model for the weak form:

    1047:   \int_\Omega \phi f_0(u, u_t, \nabla u, x, t) + \nabla\phi \cdot {\vec f}_1(u, u_t, \nabla u, x, t)

    1049: The calling sequence for the callbacks f0 and f1 is given by:

    1051: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1052: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1053: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1054: $    PetscReal t, const PetscReal x[], PetscScalar f0[])

    1056: + dim - the spatial dimension
    1057: . Nf - the number of fields
    1058: . uOff - the offset into u[] and u_t[] for each field
    1059: . uOff_x - the offset into u_x[] for each field
    1060: . u - each field evaluated at the current point
    1061: . u_t - the time derivative of each field evaluated at the current point
    1062: . u_x - the gradient of each field evaluated at the current point
    1063: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1064: . aOff_x - the offset into a_x[] for each auxiliary field
    1065: . a - each auxiliary field evaluated at the current point
    1066: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1067: . a_x - the gradient of auxiliary each field evaluated at the current point
    1068: . t - current time
    1069: . x - coordinates of the current point
    1070: . numConstants - number of constant parameters
    1071: . constants - constant parameters
    1072: - f0 - output values at the current point

    1074:   Level: intermediate

    1076: .seealso: PetscDSSetResidual()
    1077: @*/
    1078: PetscErrorCode PetscDSGetResidual(PetscDS prob, PetscInt f,
    1079:                                   void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1080:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1081:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1082:                                               PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
    1083:                                   void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1084:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1085:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1086:                                               PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
    1087: {
    1090:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    1093:   return(0);
    1094: }

    1096: /*@C
    1097:   PetscDSSetResidual - Set the pointwise residual function for a given test field

    1099:   Not collective

    1101:   Input Parameters:
    1102: + prob - The PetscDS
    1103: . f    - The test field number
    1104: . f0 - integrand for the test function term
    1105: - f1 - integrand for the test function gradient term

    1107:   Note: We are using a first order FEM model for the weak form:

    1109:   \int_\Omega \phi f_0(u, u_t, \nabla u, x, t) + \nabla\phi \cdot {\vec f}_1(u, u_t, \nabla u, x, t)

    1111: The calling sequence for the callbacks f0 and f1 is given by:

    1113: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1114: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1115: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1116: $    PetscReal t, const PetscReal x[], PetscScalar f0[])

    1118: + dim - the spatial dimension
    1119: . Nf - the number of fields
    1120: . uOff - the offset into u[] and u_t[] for each field
    1121: . uOff_x - the offset into u_x[] for each field
    1122: . u - each field evaluated at the current point
    1123: . u_t - the time derivative of each field evaluated at the current point
    1124: . u_x - the gradient of each field evaluated at the current point
    1125: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1126: . aOff_x - the offset into a_x[] for each auxiliary field
    1127: . a - each auxiliary field evaluated at the current point
    1128: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1129: . a_x - the gradient of auxiliary each field evaluated at the current point
    1130: . t - current time
    1131: . x - coordinates of the current point
    1132: . numConstants - number of constant parameters
    1133: . constants - constant parameters
    1134: - f0 - output values at the current point

    1136:   Level: intermediate

    1138: .seealso: PetscDSGetResidual()
    1139: @*/
    1140: PetscErrorCode PetscDSSetResidual(PetscDS prob, PetscInt f,
    1141:                                   void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1142:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1143:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1144:                                              PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
    1145:                                   void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1146:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1147:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1148:                                              PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
    1149: {

    1156:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    1157:   PetscDSEnlarge_Static(prob, f+1);
    1158:   prob->f[f*2+0] = f0;
    1159:   prob->f[f*2+1] = f1;
    1160:   return(0);
    1161: }

    1163: /*@C
    1164:   PetscDSHasJacobian - Signals that Jacobian functions have been set

    1166:   Not collective

    1168:   Input Parameter:
    1169: . prob - The PetscDS

    1171:   Output Parameter:
    1172: . hasJac - flag that pointwise function for the Jacobian has been set

    1174:   Level: intermediate

    1176: .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
    1177: @*/
    1178: PetscErrorCode PetscDSHasJacobian(PetscDS prob, PetscBool *hasJac)
    1179: {
    1180:   PetscInt f, g, h;

    1184:   *hasJac = PETSC_FALSE;
    1185:   for (f = 0; f < prob->Nf; ++f) {
    1186:     for (g = 0; g < prob->Nf; ++g) {
    1187:       for (h = 0; h < 4; ++h) {
    1188:         if (prob->g[(f*prob->Nf + g)*4+h]) *hasJac = PETSC_TRUE;
    1189:       }
    1190:     }
    1191:   }
    1192:   return(0);
    1193: }

    1195: /*@C
    1196:   PetscDSGetJacobian - Get the pointwise Jacobian function for given test and basis field

    1198:   Not collective

    1200:   Input Parameters:
    1201: + prob - The PetscDS
    1202: . f    - The test field number
    1203: - g    - The field number

    1205:   Output Parameters:
    1206: + g0 - integrand for the test and basis function term
    1207: . g1 - integrand for the test function and basis function gradient term
    1208: . g2 - integrand for the test function gradient and basis function term
    1209: - g3 - integrand for the test function gradient and basis function gradient term

    1211:   Note: We are using a first order FEM model for the weak form:

    1213:   \int_\Omega \phi g_0(u, u_t, \nabla u, x, t) \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \nabla \psi

    1215: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:

    1217: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1218: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1219: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1220: $    PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])

    1222: + dim - the spatial dimension
    1223: . Nf - the number of fields
    1224: . uOff - the offset into u[] and u_t[] for each field
    1225: . uOff_x - the offset into u_x[] for each field
    1226: . u - each field evaluated at the current point
    1227: . u_t - the time derivative of each field evaluated at the current point
    1228: . u_x - the gradient of each field evaluated at the current point
    1229: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1230: . aOff_x - the offset into a_x[] for each auxiliary field
    1231: . a - each auxiliary field evaluated at the current point
    1232: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1233: . a_x - the gradient of auxiliary each field evaluated at the current point
    1234: . t - current time
    1235: . u_tShift - the multiplier a for dF/dU_t
    1236: . x - coordinates of the current point
    1237: . numConstants - number of constant parameters
    1238: . constants - constant parameters
    1239: - g0 - output values at the current point

    1241:   Level: intermediate

    1243: .seealso: PetscDSSetJacobian()
    1244: @*/
    1245: PetscErrorCode PetscDSGetJacobian(PetscDS prob, PetscInt f, PetscInt g,
    1246:                                   void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1247:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1248:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1249:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    1250:                                   void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1251:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1252:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1253:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    1254:                                   void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1255:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1256:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1257:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    1258:                                   void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1259:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1260:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1261:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    1262: {
    1265:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    1266:   if ((g < 0) || (g >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, prob->Nf);
    1271:   return(0);
    1272: }

    1274: /*@C
    1275:   PetscDSSetJacobian - Set the pointwise Jacobian function for given test and basis fields

    1277:   Not collective

    1279:   Input Parameters:
    1280: + prob - The PetscDS
    1281: . f    - The test field number
    1282: . g    - The field number
    1283: . g0 - integrand for the test and basis function term
    1284: . g1 - integrand for the test function and basis function gradient term
    1285: . g2 - integrand for the test function gradient and basis function term
    1286: - g3 - integrand for the test function gradient and basis function gradient term

    1288:   Note: We are using a first order FEM model for the weak form:

    1290:   \int_\Omega \phi g_0(u, u_t, \nabla u, x, t) \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \nabla \psi

    1292: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:

    1294: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1295: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1296: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1297: $    PetscReal t, const PetscReal x[], PetscScalar g0[])

    1299: + dim - the spatial dimension
    1300: . Nf - the number of fields
    1301: . uOff - the offset into u[] and u_t[] for each field
    1302: . uOff_x - the offset into u_x[] for each field
    1303: . u - each field evaluated at the current point
    1304: . u_t - the time derivative of each field evaluated at the current point
    1305: . u_x - the gradient of each field evaluated at the current point
    1306: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1307: . aOff_x - the offset into a_x[] for each auxiliary field
    1308: . a - each auxiliary field evaluated at the current point
    1309: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1310: . a_x - the gradient of auxiliary each field evaluated at the current point
    1311: . t - current time
    1312: . u_tShift - the multiplier a for dF/dU_t
    1313: . x - coordinates of the current point
    1314: . numConstants - number of constant parameters
    1315: . constants - constant parameters
    1316: - g0 - output values at the current point

    1318:   Level: intermediate

    1320: .seealso: PetscDSGetJacobian()
    1321: @*/
    1322: PetscErrorCode PetscDSSetJacobian(PetscDS prob, PetscInt f, PetscInt g,
    1323:                                   void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1324:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1325:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1326:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    1327:                                   void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1328:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1329:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1330:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    1331:                                   void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1332:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1333:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1334:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    1335:                                   void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1336:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1337:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1338:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    1339: {

    1348:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    1349:   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
    1350:   PetscDSEnlarge_Static(prob, PetscMax(f, g)+1);
    1351:   prob->g[(f*prob->Nf + g)*4+0] = g0;
    1352:   prob->g[(f*prob->Nf + g)*4+1] = g1;
    1353:   prob->g[(f*prob->Nf + g)*4+2] = g2;
    1354:   prob->g[(f*prob->Nf + g)*4+3] = g3;
    1355:   return(0);
    1356: }

    1358: /*@C
    1359:   PetscDSUseJacobianPreconditioner - Whether to construct a Jacobian preconditioner

    1361:   Not collective

    1363:   Input Parameters:
    1364: + prob - The PetscDS
    1365: - useJacPre - flag that enables construction of a Jacobian preconditioner

    1367:   Level: intermediate

    1369: .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
    1370: @*/
    1371: PetscErrorCode PetscDSUseJacobianPreconditioner(PetscDS prob, PetscBool useJacPre)
    1372: {
    1375:   prob->useJacPre = useJacPre;
    1376:   return(0);
    1377: }

    1379: /*@C
    1380:   PetscDSHasJacobianPreconditioner - Signals that a Jacobian preconditioner matrix has been set

    1382:   Not collective

    1384:   Input Parameter:
    1385: . prob - The PetscDS

    1387:   Output Parameter:
    1388: . hasJacPre - flag that pointwise function for Jacobian preconditioner matrix has been set

    1390:   Level: intermediate

    1392: .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
    1393: @*/
    1394: PetscErrorCode PetscDSHasJacobianPreconditioner(PetscDS prob, PetscBool *hasJacPre)
    1395: {
    1396:   PetscInt f, g, h;

    1400:   *hasJacPre = PETSC_FALSE;
    1401:   if (!prob->useJacPre) return(0);
    1402:   for (f = 0; f < prob->Nf; ++f) {
    1403:     for (g = 0; g < prob->Nf; ++g) {
    1404:       for (h = 0; h < 4; ++h) {
    1405:         if (prob->gp[(f*prob->Nf + g)*4+h]) *hasJacPre = PETSC_TRUE;
    1406:       }
    1407:     }
    1408:   }
    1409:   return(0);
    1410: }

    1412: /*@C
    1413:   PetscDSGetJacobianPreconditioner - Get the pointwise Jacobian preconditioner function for given test and basis field. If this is missing, the system matrix is used to build the preconditioner.

    1415:   Not collective

    1417:   Input Parameters:
    1418: + prob - The PetscDS
    1419: . f    - The test field number
    1420: - g    - The field number

    1422:   Output Parameters:
    1423: + g0 - integrand for the test and basis function term
    1424: . g1 - integrand for the test function and basis function gradient term
    1425: . g2 - integrand for the test function gradient and basis function term
    1426: - g3 - integrand for the test function gradient and basis function gradient term

    1428:   Note: We are using a first order FEM model for the weak form:

    1430:   \int_\Omega \phi g_0(u, u_t, \nabla u, x, t) \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \nabla \psi

    1432: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:

    1434: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1435: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1436: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1437: $    PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])

    1439: + dim - the spatial dimension
    1440: . Nf - the number of fields
    1441: . uOff - the offset into u[] and u_t[] for each field
    1442: . uOff_x - the offset into u_x[] for each field
    1443: . u - each field evaluated at the current point
    1444: . u_t - the time derivative of each field evaluated at the current point
    1445: . u_x - the gradient of each field evaluated at the current point
    1446: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1447: . aOff_x - the offset into a_x[] for each auxiliary field
    1448: . a - each auxiliary field evaluated at the current point
    1449: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1450: . a_x - the gradient of auxiliary each field evaluated at the current point
    1451: . t - current time
    1452: . u_tShift - the multiplier a for dF/dU_t
    1453: . x - coordinates of the current point
    1454: . numConstants - number of constant parameters
    1455: . constants - constant parameters
    1456: - g0 - output values at the current point

    1458:   Level: intermediate

    1460: .seealso: PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
    1461: @*/
    1462: PetscErrorCode PetscDSGetJacobianPreconditioner(PetscDS prob, PetscInt f, PetscInt g,
    1463:                                   void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1464:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1465:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1466:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    1467:                                   void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1468:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1469:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1470:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    1471:                                   void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1472:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1473:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1474:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    1475:                                   void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1476:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1477:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1478:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    1479: {
    1482:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    1483:   if ((g < 0) || (g >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, prob->Nf);
    1488:   return(0);
    1489: }

    1491: /*@C
    1492:   PetscDSSetJacobianPreconditioner - Set the pointwise Jacobian preconditioner function for given test and basis fields. If this is missing, the system matrix is used to build the preconditioner.

    1494:   Not collective

    1496:   Input Parameters:
    1497: + prob - The PetscDS
    1498: . f    - The test field number
    1499: . g    - The field number
    1500: . g0 - integrand for the test and basis function term
    1501: . g1 - integrand for the test function and basis function gradient term
    1502: . g2 - integrand for the test function gradient and basis function term
    1503: - g3 - integrand for the test function gradient and basis function gradient term

    1505:   Note: We are using a first order FEM model for the weak form:

    1507:   \int_\Omega \phi g_0(u, u_t, \nabla u, x, t) \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \nabla \psi

    1509: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:

    1511: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1512: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1513: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1514: $    PetscReal t, const PetscReal x[], PetscScalar g0[])

    1516: + dim - the spatial dimension
    1517: . Nf - the number of fields
    1518: . uOff - the offset into u[] and u_t[] for each field
    1519: . uOff_x - the offset into u_x[] for each field
    1520: . u - each field evaluated at the current point
    1521: . u_t - the time derivative of each field evaluated at the current point
    1522: . u_x - the gradient of each field evaluated at the current point
    1523: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1524: . aOff_x - the offset into a_x[] for each auxiliary field
    1525: . a - each auxiliary field evaluated at the current point
    1526: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1527: . a_x - the gradient of auxiliary each field evaluated at the current point
    1528: . t - current time
    1529: . u_tShift - the multiplier a for dF/dU_t
    1530: . x - coordinates of the current point
    1531: . numConstants - number of constant parameters
    1532: . constants - constant parameters
    1533: - g0 - output values at the current point

    1535:   Level: intermediate

    1537: .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobian()
    1538: @*/
    1539: PetscErrorCode PetscDSSetJacobianPreconditioner(PetscDS prob, PetscInt f, PetscInt g,
    1540:                                   void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1541:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1542:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1543:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    1544:                                   void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1545:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1546:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1547:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    1548:                                   void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1549:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1550:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1551:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    1552:                                   void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1553:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1554:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1555:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    1556: {

    1565:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    1566:   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
    1567:   PetscDSEnlarge_Static(prob, PetscMax(f, g)+1);
    1568:   prob->gp[(f*prob->Nf + g)*4+0] = g0;
    1569:   prob->gp[(f*prob->Nf + g)*4+1] = g1;
    1570:   prob->gp[(f*prob->Nf + g)*4+2] = g2;
    1571:   prob->gp[(f*prob->Nf + g)*4+3] = g3;
    1572:   return(0);
    1573: }

    1575: /*@C
    1576:   PetscDSHasDynamicJacobian - Signals that a dynamic Jacobian, dF/du_t, has been set

    1578:   Not collective

    1580:   Input Parameter:
    1581: . prob - The PetscDS

    1583:   Output Parameter:
    1584: . hasDynJac - flag that pointwise function for dynamic Jacobian has been set

    1586:   Level: intermediate

    1588: .seealso: PetscDSGetDynamicJacobian(), PetscDSSetDynamicJacobian(), PetscDSGetJacobian()
    1589: @*/
    1590: PetscErrorCode PetscDSHasDynamicJacobian(PetscDS prob, PetscBool *hasDynJac)
    1591: {
    1592:   PetscInt f, g, h;

    1596:   *hasDynJac = PETSC_FALSE;
    1597:   for (f = 0; f < prob->Nf; ++f) {
    1598:     for (g = 0; g < prob->Nf; ++g) {
    1599:       for (h = 0; h < 4; ++h) {
    1600:         if (prob->gt[(f*prob->Nf + g)*4+h]) *hasDynJac = PETSC_TRUE;
    1601:       }
    1602:     }
    1603:   }
    1604:   return(0);
    1605: }

    1607: /*@C
    1608:   PetscDSGetDynamicJacobian - Get the pointwise dynamic Jacobian, dF/du_t, function for given test and basis field

    1610:   Not collective

    1612:   Input Parameters:
    1613: + prob - The PetscDS
    1614: . f    - The test field number
    1615: - g    - The field number

    1617:   Output Parameters:
    1618: + g0 - integrand for the test and basis function term
    1619: . g1 - integrand for the test function and basis function gradient term
    1620: . g2 - integrand for the test function gradient and basis function term
    1621: - g3 - integrand for the test function gradient and basis function gradient term

    1623:   Note: We are using a first order FEM model for the weak form:

    1625:   \int_\Omega \phi g_0(u, u_t, \nabla u, x, t) \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \nabla \psi

    1627: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:

    1629: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1630: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1631: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1632: $    PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])

    1634: + dim - the spatial dimension
    1635: . Nf - the number of fields
    1636: . uOff - the offset into u[] and u_t[] for each field
    1637: . uOff_x - the offset into u_x[] for each field
    1638: . u - each field evaluated at the current point
    1639: . u_t - the time derivative of each field evaluated at the current point
    1640: . u_x - the gradient of each field evaluated at the current point
    1641: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1642: . aOff_x - the offset into a_x[] for each auxiliary field
    1643: . a - each auxiliary field evaluated at the current point
    1644: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1645: . a_x - the gradient of auxiliary each field evaluated at the current point
    1646: . t - current time
    1647: . u_tShift - the multiplier a for dF/dU_t
    1648: . x - coordinates of the current point
    1649: . numConstants - number of constant parameters
    1650: . constants - constant parameters
    1651: - g0 - output values at the current point

    1653:   Level: intermediate

    1655: .seealso: PetscDSSetJacobian()
    1656: @*/
    1657: PetscErrorCode PetscDSGetDynamicJacobian(PetscDS prob, PetscInt f, PetscInt g,
    1658:                                          void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1659:                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1660:                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1661:                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    1662:                                          void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1663:                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1664:                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1665:                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    1666:                                          void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1667:                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1668:                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1669:                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    1670:                                          void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1671:                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1672:                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1673:                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    1674: {
    1677:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    1678:   if ((g < 0) || (g >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, prob->Nf);
    1683:   return(0);
    1684: }

    1686: /*@C
    1687:   PetscDSSetDynamicJacobian - Set the pointwise dynamic Jacobian, dF/du_t, function for given test and basis fields

    1689:   Not collective

    1691:   Input Parameters:
    1692: + prob - The PetscDS
    1693: . f    - The test field number
    1694: . g    - The field number
    1695: . g0 - integrand for the test and basis function term
    1696: . g1 - integrand for the test function and basis function gradient term
    1697: . g2 - integrand for the test function gradient and basis function term
    1698: - g3 - integrand for the test function gradient and basis function gradient term

    1700:   Note: We are using a first order FEM model for the weak form:

    1702:   \int_\Omega \phi g_0(u, u_t, \nabla u, x, t) \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \nabla \psi

    1704: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:

    1706: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1707: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1708: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1709: $    PetscReal t, const PetscReal x[], PetscScalar g0[])

    1711: + dim - the spatial dimension
    1712: . Nf - the number of fields
    1713: . uOff - the offset into u[] and u_t[] for each field
    1714: . uOff_x - the offset into u_x[] for each field
    1715: . u - each field evaluated at the current point
    1716: . u_t - the time derivative of each field evaluated at the current point
    1717: . u_x - the gradient of each field evaluated at the current point
    1718: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1719: . aOff_x - the offset into a_x[] for each auxiliary field
    1720: . a - each auxiliary field evaluated at the current point
    1721: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1722: . a_x - the gradient of auxiliary each field evaluated at the current point
    1723: . t - current time
    1724: . u_tShift - the multiplier a for dF/dU_t
    1725: . x - coordinates of the current point
    1726: . numConstants - number of constant parameters
    1727: . constants - constant parameters
    1728: - g0 - output values at the current point

    1730:   Level: intermediate

    1732: .seealso: PetscDSGetJacobian()
    1733: @*/
    1734: PetscErrorCode PetscDSSetDynamicJacobian(PetscDS prob, PetscInt f, PetscInt g,
    1735:                                          void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1736:                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1737:                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1738:                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    1739:                                          void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1740:                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1741:                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1742:                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    1743:                                          void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1744:                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1745:                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1746:                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    1747:                                          void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1748:                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1749:                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1750:                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    1751: {

    1760:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    1761:   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
    1762:   PetscDSEnlarge_Static(prob, PetscMax(f, g)+1);
    1763:   prob->gt[(f*prob->Nf + g)*4+0] = g0;
    1764:   prob->gt[(f*prob->Nf + g)*4+1] = g1;
    1765:   prob->gt[(f*prob->Nf + g)*4+2] = g2;
    1766:   prob->gt[(f*prob->Nf + g)*4+3] = g3;
    1767:   return(0);
    1768: }

    1770: /*@C
    1771:   PetscDSGetRiemannSolver - Returns the Riemann solver for the given field

    1773:   Not collective

    1775:   Input Arguments:
    1776: + prob - The PetscDS object
    1777: - f    - The field number

    1779:   Output Argument:
    1780: . r    - Riemann solver

    1782:   Calling sequence for r:

    1784: $ r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx)

    1786: + dim  - The spatial dimension
    1787: . Nf   - The number of fields
    1788: . x    - The coordinates at a point on the interface
    1789: . n    - The normal vector to the interface
    1790: . uL   - The state vector to the left of the interface
    1791: . uR   - The state vector to the right of the interface
    1792: . flux - output array of flux through the interface
    1793: . numConstants - number of constant parameters
    1794: . constants - constant parameters
    1795: - ctx  - optional user context

    1797:   Level: intermediate

    1799: .seealso: PetscDSSetRiemannSolver()
    1800: @*/
    1801: PetscErrorCode PetscDSGetRiemannSolver(PetscDS prob, PetscInt f,
    1802:                                        void (**r)(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscInt numConstants, const PetscScalar constants[], PetscScalar flux[], void *ctx))
    1803: {
    1806:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    1808:   *r = prob->r[f];
    1809:   return(0);
    1810: }

    1812: /*@C
    1813:   PetscDSSetRiemannSolver - Sets the Riemann solver for the given field

    1815:   Not collective

    1817:   Input Arguments:
    1818: + prob - The PetscDS object
    1819: . f    - The field number
    1820: - r    - Riemann solver

    1822:   Calling sequence for r:

    1824: $ r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx)

    1826: + dim  - The spatial dimension
    1827: . Nf   - The number of fields
    1828: . x    - The coordinates at a point on the interface
    1829: . n    - The normal vector to the interface
    1830: . uL   - The state vector to the left of the interface
    1831: . uR   - The state vector to the right of the interface
    1832: . flux - output array of flux through the interface
    1833: . numConstants - number of constant parameters
    1834: . constants - constant parameters
    1835: - ctx  - optional user context

    1837:   Level: intermediate

    1839: .seealso: PetscDSGetRiemannSolver()
    1840: @*/
    1841: PetscErrorCode PetscDSSetRiemannSolver(PetscDS prob, PetscInt f,
    1842:                                        void (*r)(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscInt numConstants, const PetscScalar constants[], PetscScalar flux[], void *ctx))
    1843: {

    1849:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    1850:   PetscDSEnlarge_Static(prob, f+1);
    1851:   prob->r[f] = r;
    1852:   return(0);
    1853: }

    1855: /*@C
    1856:   PetscDSGetUpdate - Get the pointwise update function for a given field

    1858:   Not collective

    1860:   Input Parameters:
    1861: + prob - The PetscDS
    1862: - f    - The field number

    1864:   Output Parameters:
    1865: . update - update function

    1867:   Note: The calling sequence for the callback update is given by:

    1869: $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1870: $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1871: $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1872: $        PetscReal t, const PetscReal x[], PetscScalar uNew[])

    1874: + dim - the spatial dimension
    1875: . Nf - the number of fields
    1876: . uOff - the offset into u[] and u_t[] for each field
    1877: . uOff_x - the offset into u_x[] for each field
    1878: . u - each field evaluated at the current point
    1879: . u_t - the time derivative of each field evaluated at the current point
    1880: . u_x - the gradient of each field evaluated at the current point
    1881: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1882: . aOff_x - the offset into a_x[] for each auxiliary field
    1883: . a - each auxiliary field evaluated at the current point
    1884: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1885: . a_x - the gradient of auxiliary each field evaluated at the current point
    1886: . t - current time
    1887: . x - coordinates of the current point
    1888: - uNew - new value for field at the current point

    1890:   Level: intermediate

    1892: .seealso: PetscDSSetUpdate(), PetscDSSetResidual()
    1893: @*/
    1894: PetscErrorCode PetscDSGetUpdate(PetscDS prob, PetscInt f,
    1895:                                   void (**update)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1896:                                                   const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1897:                                                   const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1898:                                                   PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[]))
    1899: {
    1902:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    1904:   return(0);
    1905: }

    1907: /*@C
    1908:   PetscDSSetUpdate - Set the pointwise update function for a given field

    1910:   Not collective

    1912:   Input Parameters:
    1913: + prob   - The PetscDS
    1914: . f      - The field number
    1915: - update - update function

    1917:   Note: The calling sequence for the callback update is given by:

    1919: $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1920: $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1921: $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1922: $        PetscReal t, const PetscReal x[], PetscScalar uNew[])

    1924: + dim - the spatial dimension
    1925: . Nf - the number of fields
    1926: . uOff - the offset into u[] and u_t[] for each field
    1927: . uOff_x - the offset into u_x[] for each field
    1928: . u - each field evaluated at the current point
    1929: . u_t - the time derivative of each field evaluated at the current point
    1930: . u_x - the gradient of each field evaluated at the current point
    1931: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1932: . aOff_x - the offset into a_x[] for each auxiliary field
    1933: . a - each auxiliary field evaluated at the current point
    1934: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1935: . a_x - the gradient of auxiliary each field evaluated at the current point
    1936: . t - current time
    1937: . x - coordinates of the current point
    1938: - uNew - new field values at the current point

    1940:   Level: intermediate

    1942: .seealso: PetscDSGetResidual()
    1943: @*/
    1944: PetscErrorCode PetscDSSetUpdate(PetscDS prob, PetscInt f,
    1945:                                 void (*update)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1946:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1947:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1948:                                                PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[]))
    1949: {

    1955:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    1956:   PetscDSEnlarge_Static(prob, f+1);
    1957:   prob->update[f] = update;
    1958:   return(0);
    1959: }

    1961: PetscErrorCode PetscDSGetContext(PetscDS prob, PetscInt f, void **ctx)
    1962: {
    1965:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    1967:   *ctx = prob->ctx[f];
    1968:   return(0);
    1969: }

    1971: PetscErrorCode PetscDSSetContext(PetscDS prob, PetscInt f, void *ctx)
    1972: {

    1977:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    1978:   PetscDSEnlarge_Static(prob, f+1);
    1979:   prob->ctx[f] = ctx;
    1980:   return(0);
    1981: }

    1983: /*@C
    1984:   PetscDSGetBdResidual - Get the pointwise boundary residual function for a given test field

    1986:   Not collective

    1988:   Input Parameters:
    1989: + prob - The PetscDS
    1990: - f    - The test field number

    1992:   Output Parameters:
    1993: + f0 - boundary integrand for the test function term
    1994: - f1 - boundary integrand for the test function gradient term

    1996:   Note: We are using a first order FEM model for the weak form:

    1998:   \int_\Gamma \phi {\vec f}_0(u, u_t, \nabla u, x, t) \cdot \hat n + \nabla\phi \cdot {\overleftrightarrow f}_1(u, u_t, \nabla u, x, t) \cdot \hat n

    2000: The calling sequence for the callbacks f0 and f1 is given by:

    2002: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2003: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2004: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2005: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])

    2007: + dim - the spatial dimension
    2008: . Nf - the number of fields
    2009: . uOff - the offset into u[] and u_t[] for each field
    2010: . uOff_x - the offset into u_x[] for each field
    2011: . u - each field evaluated at the current point
    2012: . u_t - the time derivative of each field evaluated at the current point
    2013: . u_x - the gradient of each field evaluated at the current point
    2014: . aOff - the offset into a[] and a_t[] for each auxiliary field
    2015: . aOff_x - the offset into a_x[] for each auxiliary field
    2016: . a - each auxiliary field evaluated at the current point
    2017: . a_t - the time derivative of each auxiliary field evaluated at the current point
    2018: . a_x - the gradient of auxiliary each field evaluated at the current point
    2019: . t - current time
    2020: . x - coordinates of the current point
    2021: . n - unit normal at the current point
    2022: . numConstants - number of constant parameters
    2023: . constants - constant parameters
    2024: - f0 - output values at the current point

    2026:   Level: intermediate

    2028: .seealso: PetscDSSetBdResidual()
    2029: @*/
    2030: PetscErrorCode PetscDSGetBdResidual(PetscDS prob, PetscInt f,
    2031:                                     void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2032:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2033:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2034:                                                 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
    2035:                                     void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2036:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2037:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2038:                                                 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
    2039: {
    2042:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    2045:   return(0);
    2046: }

    2048: /*@C
    2049:   PetscDSSetBdResidual - Get the pointwise boundary residual function for a given test field

    2051:   Not collective

    2053:   Input Parameters:
    2054: + prob - The PetscDS
    2055: . f    - The test field number
    2056: . f0 - boundary integrand for the test function term
    2057: - f1 - boundary integrand for the test function gradient term

    2059:   Note: We are using a first order FEM model for the weak form:

    2061:   \int_\Gamma \phi {\vec f}_0(u, u_t, \nabla u, x, t) \cdot \hat n + \nabla\phi \cdot {\overleftrightarrow f}_1(u, u_t, \nabla u, x, t) \cdot \hat n

    2063: The calling sequence for the callbacks f0 and f1 is given by:

    2065: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2066: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2067: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2068: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])

    2070: + dim - the spatial dimension
    2071: . Nf - the number of fields
    2072: . uOff - the offset into u[] and u_t[] for each field
    2073: . uOff_x - the offset into u_x[] for each field
    2074: . u - each field evaluated at the current point
    2075: . u_t - the time derivative of each field evaluated at the current point
    2076: . u_x - the gradient of each field evaluated at the current point
    2077: . aOff - the offset into a[] and a_t[] for each auxiliary field
    2078: . aOff_x - the offset into a_x[] for each auxiliary field
    2079: . a - each auxiliary field evaluated at the current point
    2080: . a_t - the time derivative of each auxiliary field evaluated at the current point
    2081: . a_x - the gradient of auxiliary each field evaluated at the current point
    2082: . t - current time
    2083: . x - coordinates of the current point
    2084: . n - unit normal at the current point
    2085: . numConstants - number of constant parameters
    2086: . constants - constant parameters
    2087: - f0 - output values at the current point

    2089:   Level: intermediate

    2091: .seealso: PetscDSGetBdResidual()
    2092: @*/
    2093: PetscErrorCode PetscDSSetBdResidual(PetscDS prob, PetscInt f,
    2094:                                     void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2095:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2096:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2097:                                                PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
    2098:                                     void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2099:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2100:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2101:                                                PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
    2102: {

    2107:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    2108:   PetscDSEnlarge_Static(prob, f+1);
    2111:   return(0);
    2112: }

    2114: /*@
    2115:   PetscDSHasBdJacobian - Signals that boundary Jacobian functions have been set

    2117:   Not collective

    2119:   Input Parameter:
    2120: . prob - The PetscDS

    2122:   Output Parameter:
    2123: . hasBdJac - flag that pointwise function for the boundary Jacobian has been set

    2125:   Level: intermediate

    2127: .seealso: PetscDSHasJacobian(), PetscDSSetBdJacobian(), PetscDSGetBdJacobian()
    2128: @*/
    2129: PetscErrorCode PetscDSHasBdJacobian(PetscDS prob, PetscBool *hasBdJac)
    2130: {
    2131:   PetscInt f, g, h;

    2135:   *hasBdJac = PETSC_FALSE;
    2136:   for (f = 0; f < prob->Nf; ++f) {
    2137:     for (g = 0; g < prob->Nf; ++g) {
    2138:       for (h = 0; h < 4; ++h) {
    2139:         if (prob->gBd[(f*prob->Nf + g)*4+h]) *hasBdJac = PETSC_TRUE;
    2140:       }
    2141:     }
    2142:   }
    2143:   return(0);
    2144: }

    2146: /*@C
    2147:   PetscDSGetBdJacobian - Get the pointwise boundary Jacobian function for given test and basis field

    2149:   Not collective

    2151:   Input Parameters:
    2152: + prob - The PetscDS
    2153: . f    - The test field number
    2154: - g    - The field number

    2156:   Output Parameters:
    2157: + g0 - integrand for the test and basis function term
    2158: . g1 - integrand for the test function and basis function gradient term
    2159: . g2 - integrand for the test function gradient and basis function term
    2160: - g3 - integrand for the test function gradient and basis function gradient term

    2162:   Note: We are using a first order FEM model for the weak form:

    2164:   \int_\Gamma \phi {\vec g}_0(u, u_t, \nabla u, x, t) \cdot \hat n \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \cdot \hat n \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \cdot \hat n \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \hat n \cdot \nabla \psi

    2166: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:

    2168: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2169: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2170: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2171: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[])

    2173: + dim - the spatial dimension
    2174: . Nf - the number of fields
    2175: . uOff - the offset into u[] and u_t[] for each field
    2176: . uOff_x - the offset into u_x[] for each field
    2177: . u - each field evaluated at the current point
    2178: . u_t - the time derivative of each field evaluated at the current point
    2179: . u_x - the gradient of each field evaluated at the current point
    2180: . aOff - the offset into a[] and a_t[] for each auxiliary field
    2181: . aOff_x - the offset into a_x[] for each auxiliary field
    2182: . a - each auxiliary field evaluated at the current point
    2183: . a_t - the time derivative of each auxiliary field evaluated at the current point
    2184: . a_x - the gradient of auxiliary each field evaluated at the current point
    2185: . t - current time
    2186: . u_tShift - the multiplier a for dF/dU_t
    2187: . x - coordinates of the current point
    2188: . n - normal at the current point
    2189: . numConstants - number of constant parameters
    2190: . constants - constant parameters
    2191: - g0 - output values at the current point

    2193:   Level: intermediate

    2195: .seealso: PetscDSSetBdJacobian()
    2196: @*/
    2197: PetscErrorCode PetscDSGetBdJacobian(PetscDS prob, PetscInt f, PetscInt g,
    2198:                                     void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2199:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2200:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2201:                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    2202:                                     void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2203:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2204:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2205:                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    2206:                                     void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2207:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2208:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2209:                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    2210:                                     void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2211:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2212:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2213:                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    2214: {
    2217:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    2218:   if ((g < 0) || (g >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, prob->Nf);
    2223:   return(0);
    2224: }

    2226: /*@C
    2227:   PetscDSSetBdJacobian - Set the pointwise boundary Jacobian function for given test and basis field

    2229:   Not collective

    2231:   Input Parameters:
    2232: + prob - The PetscDS
    2233: . f    - The test field number
    2234: . g    - The field number
    2235: . g0 - integrand for the test and basis function term
    2236: . g1 - integrand for the test function and basis function gradient term
    2237: . g2 - integrand for the test function gradient and basis function term
    2238: - g3 - integrand for the test function gradient and basis function gradient term

    2240:   Note: We are using a first order FEM model for the weak form:

    2242:   \int_\Gamma \phi {\vec g}_0(u, u_t, \nabla u, x, t) \cdot \hat n \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \cdot \hat n \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \cdot \hat n \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \hat n \cdot \nabla \psi

    2244: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:

    2246: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2247: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2248: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2249: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[])

    2251: + dim - the spatial dimension
    2252: . Nf - the number of fields
    2253: . uOff - the offset into u[] and u_t[] for each field
    2254: . uOff_x - the offset into u_x[] for each field
    2255: . u - each field evaluated at the current point
    2256: . u_t - the time derivative of each field evaluated at the current point
    2257: . u_x - the gradient of each field evaluated at the current point
    2258: . aOff - the offset into a[] and a_t[] for each auxiliary field
    2259: . aOff_x - the offset into a_x[] for each auxiliary field
    2260: . a - each auxiliary field evaluated at the current point
    2261: . a_t - the time derivative of each auxiliary field evaluated at the current point
    2262: . a_x - the gradient of auxiliary each field evaluated at the current point
    2263: . t - current time
    2264: . u_tShift - the multiplier a for dF/dU_t
    2265: . x - coordinates of the current point
    2266: . n - normal at the current point
    2267: . numConstants - number of constant parameters
    2268: . constants - constant parameters
    2269: - g0 - output values at the current point

    2271:   Level: intermediate

    2273: .seealso: PetscDSGetBdJacobian()
    2274: @*/
    2275: PetscErrorCode PetscDSSetBdJacobian(PetscDS prob, PetscInt f, PetscInt g,
    2276:                                     void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2277:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2278:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2279:                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    2280:                                     void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2281:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2282:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2283:                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    2284:                                     void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2285:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2286:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2287:                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    2288:                                     void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2289:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2290:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2291:                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    2292: {

    2301:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    2302:   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
    2303:   PetscDSEnlarge_Static(prob, PetscMax(f, g)+1);
    2304:   prob->gBd[(f*prob->Nf + g)*4+0] = g0;
    2305:   prob->gBd[(f*prob->Nf + g)*4+1] = g1;
    2306:   prob->gBd[(f*prob->Nf + g)*4+2] = g2;
    2307:   prob->gBd[(f*prob->Nf + g)*4+3] = g3;
    2308:   return(0);
    2309: }

    2311: /*@
    2312:   PetscDSHasBdJacobianPreconditioner - Signals that boundary Jacobian preconditioner functions have been set

    2314:   Not collective

    2316:   Input Parameter:
    2317: . prob - The PetscDS

    2319:   Output Parameter:
    2320: . hasBdJac - flag that pointwise function for the boundary Jacobian preconditioner has been set

    2322:   Level: intermediate

    2324: .seealso: PetscDSHasJacobian(), PetscDSSetBdJacobian(), PetscDSGetBdJacobian()
    2325: @*/
    2326: PetscErrorCode PetscDSHasBdJacobianPreconditioner(PetscDS prob, PetscBool *hasBdJacPre)
    2327: {
    2328:   PetscInt f, g, h;

    2332:   *hasBdJacPre = PETSC_FALSE;
    2333:   for (f = 0; f < prob->Nf; ++f) {
    2334:     for (g = 0; g < prob->Nf; ++g) {
    2335:       for (h = 0; h < 4; ++h) {
    2336:         if (prob->gpBd[(f*prob->Nf + g)*4+h]) *hasBdJacPre = PETSC_TRUE;
    2337:       }
    2338:     }
    2339:   }
    2340:   return(0);
    2341: }

    2343: /*@C
    2344:   PetscDSGetBdJacobianPreconditioner - Get the pointwise boundary Jacobian preconditioner function for given test and basis field

    2346:   Not collective

    2348:   Input Parameters:
    2349: + prob - The PetscDS
    2350: . f    - The test field number
    2351: - g    - The field number

    2353:   Output Parameters:
    2354: + g0 - integrand for the test and basis function term
    2355: . g1 - integrand for the test function and basis function gradient term
    2356: . g2 - integrand for the test function gradient and basis function term
    2357: - g3 - integrand for the test function gradient and basis function gradient term

    2359:   Note: We are using a first order FEM model for the weak form:

    2361:   \int_\Gamma \phi {\vec g}_0(u, u_t, \nabla u, x, t) \cdot \hat n \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \cdot \hat n \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \cdot \hat n \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \hat n \cdot \nabla \psi

    2363: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:

    2365: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2366: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2367: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2368: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])

    2370: + dim - the spatial dimension
    2371: . Nf - the number of fields
    2372: . NfAux - the number of auxiliary fields
    2373: . uOff - the offset into u[] and u_t[] for each field
    2374: . uOff_x - the offset into u_x[] for each field
    2375: . u - each field evaluated at the current point
    2376: . u_t - the time derivative of each field evaluated at the current point
    2377: . u_x - the gradient of each field evaluated at the current point
    2378: . aOff - the offset into a[] and a_t[] for each auxiliary field
    2379: . aOff_x - the offset into a_x[] for each auxiliary field
    2380: . a - each auxiliary field evaluated at the current point
    2381: . a_t - the time derivative of each auxiliary field evaluated at the current point
    2382: . a_x - the gradient of auxiliary each field evaluated at the current point
    2383: . t - current time
    2384: . u_tShift - the multiplier a for dF/dU_t
    2385: . x - coordinates of the current point
    2386: . n - normal at the current point
    2387: . numConstants - number of constant parameters
    2388: . constants - constant parameters
    2389: - g0 - output values at the current point

    2391:   This is not yet available in Fortran.

    2393:   Level: intermediate

    2395: .seealso: PetscDSSetBdJacobianPreconditioner()
    2396: @*/
    2397: PetscErrorCode PetscDSGetBdJacobianPreconditioner(PetscDS prob, PetscInt f, PetscInt g,
    2398:                                                   void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2399:                                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2400:                                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2401:                                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    2402:                                                   void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2403:                                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2404:                                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2405:                                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    2406:                                                   void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2407:                                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2408:                                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2409:                                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    2410:                                                   void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2411:                                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2412:                                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2413:                                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    2414: {
    2417:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    2418:   if ((g < 0) || (g >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, prob->Nf);
    2423:   return(0);
    2424: }

    2426: /*@C
    2427:   PetscDSSetBdJacobianPreconditioner - Set the pointwise boundary Jacobian preconditioner function for given test and basis field

    2429:   Not collective

    2431:   Input Parameters:
    2432: + prob - The PetscDS
    2433: . f    - The test field number
    2434: . g    - The field number
    2435: . g0 - integrand for the test and basis function term
    2436: . g1 - integrand for the test function and basis function gradient term
    2437: . g2 - integrand for the test function gradient and basis function term
    2438: - g3 - integrand for the test function gradient and basis function gradient term

    2440:   Note: We are using a first order FEM model for the weak form:

    2442:   \int_\Gamma \phi {\vec g}_0(u, u_t, \nabla u, x, t) \cdot \hat n \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \cdot \hat n \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \cdot \hat n \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \hat n \cdot \nabla \psi

    2444: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:

    2446: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2447: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2448: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2449: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])

    2451: + dim - the spatial dimension
    2452: . Nf - the number of fields
    2453: . NfAux - the number of auxiliary fields
    2454: . uOff - the offset into u[] and u_t[] for each field
    2455: . uOff_x - the offset into u_x[] for each field
    2456: . u - each field evaluated at the current point
    2457: . u_t - the time derivative of each field evaluated at the current point
    2458: . u_x - the gradient of each field evaluated at the current point
    2459: . aOff - the offset into a[] and a_t[] for each auxiliary field
    2460: . aOff_x - the offset into a_x[] for each auxiliary field
    2461: . a - each auxiliary field evaluated at the current point
    2462: . a_t - the time derivative of each auxiliary field evaluated at the current point
    2463: . a_x - the gradient of auxiliary each field evaluated at the current point
    2464: . t - current time
    2465: . u_tShift - the multiplier a for dF/dU_t
    2466: . x - coordinates of the current point
    2467: . n - normal at the current point
    2468: . numConstants - number of constant parameters
    2469: . constants - constant parameters
    2470: - g0 - output values at the current point

    2472:   This is not yet available in Fortran.

    2474:   Level: intermediate

    2476: .seealso: PetscDSGetBdJacobianPreconditioner()
    2477: @*/
    2478: PetscErrorCode PetscDSSetBdJacobianPreconditioner(PetscDS prob, PetscInt f, PetscInt g,
    2479:                                                   void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2480:                                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2481:                                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2482:                                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    2483:                                                   void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2484:                                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2485:                                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2486:                                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    2487:                                                   void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2488:                                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2489:                                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2490:                                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    2491:                                                   void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2492:                                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2493:                                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2494:                                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    2495: {

    2504:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    2505:   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
    2506:   PetscDSEnlarge_Static(prob, PetscMax(f, g)+1);
    2507:   prob->gpBd[(f*prob->Nf + g)*4+0] = g0;
    2508:   prob->gpBd[(f*prob->Nf + g)*4+1] = g1;
    2509:   prob->gpBd[(f*prob->Nf + g)*4+2] = g2;
    2510:   prob->gpBd[(f*prob->Nf + g)*4+3] = g3;
    2511:   return(0);
    2512: }

    2514: /*@C
    2515:   PetscDSGetExactSolution - Get the pointwise exact solution function for a given test field

    2517:   Not collective

    2519:   Input Parameters:
    2520: + prob - The PetscDS
    2521: - f    - The test field number

    2523:   Output Parameter:
    2524: + exactSol - exact solution for the test field
    2525: - exactCtx - exact solution context

    2527:   Note: The calling sequence for the solution functions is given by:

    2529: $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)

    2531: + dim - the spatial dimension
    2532: . t - current time
    2533: . x - coordinates of the current point
    2534: . Nc - the number of field components
    2535: . u - the solution field evaluated at the current point
    2536: - ctx - a user context

    2538:   Level: intermediate

    2540: .seealso: PetscDSSetExactSolution(), PetscDSGetExactSolutionTimeDerivative()
    2541: @*/
    2542: PetscErrorCode PetscDSGetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx)
    2543: {
    2546:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    2549:   return(0);
    2550: }

    2552: /*@C
    2553:   PetscDSSetExactSolution - Set the pointwise exact solution function for a given test field

    2555:   Not collective

    2557:   Input Parameters:
    2558: + prob - The PetscDS
    2559: . f    - The test field number
    2560: . sol  - solution function for the test fields
    2561: - ctx  - solution context or NULL

    2563:   Note: The calling sequence for solution functions is given by:

    2565: $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)

    2567: + dim - the spatial dimension
    2568: . t - current time
    2569: . x - coordinates of the current point
    2570: . Nc - the number of field components
    2571: . u - the solution field evaluated at the current point
    2572: - ctx - a user context

    2574:   Level: intermediate

    2576: .seealso: PetscDSGetExactSolution()
    2577: @*/
    2578: PetscErrorCode PetscDSSetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx)
    2579: {

    2584:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    2585:   PetscDSEnlarge_Static(prob, f+1);
    2588:   return(0);
    2589: }

    2591: /*@C
    2592:   PetscDSGetExactSolutionTimeDerivative - Get the pointwise time derivative of the exact solution function for a given test field

    2594:   Not collective

    2596:   Input Parameters:
    2597: + prob - The PetscDS
    2598: - f    - The test field number

    2600:   Output Parameter:
    2601: + exactSol - time derivative of the exact solution for the test field
    2602: - exactCtx - time derivative of the exact solution context

    2604:   Note: The calling sequence for the solution functions is given by:

    2606: $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)

    2608: + dim - the spatial dimension
    2609: . t - current time
    2610: . x - coordinates of the current point
    2611: . Nc - the number of field components
    2612: . u - the solution field evaluated at the current point
    2613: - ctx - a user context

    2615:   Level: intermediate

    2617: .seealso: PetscDSSetExactSolutionTimeDerivative(), PetscDSGetExactSolution()
    2618: @*/
    2619: PetscErrorCode PetscDSGetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx)
    2620: {
    2623:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    2626:   return(0);
    2627: }

    2629: /*@C
    2630:   PetscDSSetExactSolutionTimeDerivative - Set the pointwise time derivative of the exact solution function for a given test field

    2632:   Not collective

    2634:   Input Parameters:
    2635: + prob - The PetscDS
    2636: . f    - The test field number
    2637: . sol  - time derivative of the solution function for the test fields
    2638: - ctx  - time derivative of the solution context or NULL

    2640:   Note: The calling sequence for solution functions is given by:

    2642: $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)

    2644: + dim - the spatial dimension
    2645: . t - current time
    2646: . x - coordinates of the current point
    2647: . Nc - the number of field components
    2648: . u - the solution field evaluated at the current point
    2649: - ctx - a user context

    2651:   Level: intermediate

    2653: .seealso: PetscDSGetExactSolutionTimeDerivative(), PetscDSSetExactSolution()
    2654: @*/
    2655: PetscErrorCode PetscDSSetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx)
    2656: {

    2661:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    2662:   PetscDSEnlarge_Static(prob, f+1);
    2665:   return(0);
    2666: }

    2668: /*@C
    2669:   PetscDSGetConstants - Returns the array of constants passed to point functions

    2671:   Not collective

    2673:   Input Parameter:
    2674: . prob - The PetscDS object

    2676:   Output Parameters:
    2677: + numConstants - The number of constants
    2678: - constants    - The array of constants, NULL if there are none

    2680:   Level: intermediate

    2682: .seealso: PetscDSSetConstants(), PetscDSCreate()
    2683: @*/
    2684: PetscErrorCode PetscDSGetConstants(PetscDS prob, PetscInt *numConstants, const PetscScalar *constants[])
    2685: {
    2690:   return(0);
    2691: }

    2693: /*@C
    2694:   PetscDSSetConstants - Set the array of constants passed to point functions

    2696:   Not collective

    2698:   Input Parameters:
    2699: + prob         - The PetscDS object
    2700: . numConstants - The number of constants
    2701: - constants    - The array of constants, NULL if there are none

    2703:   Level: intermediate

    2705: .seealso: PetscDSGetConstants(), PetscDSCreate()
    2706: @*/
    2707: PetscErrorCode PetscDSSetConstants(PetscDS prob, PetscInt numConstants, PetscScalar constants[])
    2708: {

    2713:   if (numConstants != prob->numConstants) {
    2714:     PetscFree(prob->constants);
    2715:     prob->numConstants = numConstants;
    2716:     if (prob->numConstants) {
    2717:       PetscMalloc1(prob->numConstants, &prob->constants);
    2718:     } else {
    2719:       prob->constants = NULL;
    2720:     }
    2721:   }
    2722:   if (prob->numConstants) {
    2724:     PetscArraycpy(prob->constants, constants, prob->numConstants);
    2725:   }
    2726:   return(0);
    2727: }

    2729: /*@
    2730:   PetscDSGetFieldIndex - Returns the index of the given field

    2732:   Not collective

    2734:   Input Parameters:
    2735: + prob - The PetscDS object
    2736: - disc - The discretization object

    2738:   Output Parameter:
    2739: . f - The field number

    2741:   Level: beginner

    2743: .seealso: PetscGetDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    2744: @*/
    2745: PetscErrorCode PetscDSGetFieldIndex(PetscDS prob, PetscObject disc, PetscInt *f)
    2746: {
    2747:   PetscInt g;

    2752:   *f = -1;
    2753:   for (g = 0; g < prob->Nf; ++g) {if (disc == prob->disc[g]) break;}
    2754:   if (g == prob->Nf) SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Field not found in PetscDS.");
    2755:   *f = g;
    2756:   return(0);
    2757: }

    2759: /*@
    2760:   PetscDSGetFieldSize - Returns the size of the given field in the full space basis

    2762:   Not collective

    2764:   Input Parameters:
    2765: + prob - The PetscDS object
    2766: - f - The field number

    2768:   Output Parameter:
    2769: . size - The size

    2771:   Level: beginner

    2773: .seealso: PetscDSGetFieldOffset(), PetscDSGetNumFields(), PetscDSCreate()
    2774: @*/
    2775: PetscErrorCode PetscDSGetFieldSize(PetscDS prob, PetscInt f, PetscInt *size)
    2776: {

    2782:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    2783:   PetscDSSetUp(prob);
    2784:   *size = prob->Nb[f];
    2785:   return(0);
    2786: }

    2788: /*@
    2789:   PetscDSGetFieldOffset - Returns the offset of the given field in the full space basis

    2791:   Not collective

    2793:   Input Parameters:
    2794: + prob - The PetscDS object
    2795: - f - The field number

    2797:   Output Parameter:
    2798: . off - The offset

    2800:   Level: beginner

    2802: .seealso: PetscDSGetFieldSize(), PetscDSGetNumFields(), PetscDSCreate()
    2803: @*/
    2804: PetscErrorCode PetscDSGetFieldOffset(PetscDS prob, PetscInt f, PetscInt *off)
    2805: {
    2806:   PetscInt       size, g;

    2812:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    2813:   *off = 0;
    2814:   for (g = 0; g < f; ++g) {
    2815:     PetscDSGetFieldSize(prob, g, &size);
    2816:     *off += size;
    2817:   }
    2818:   return(0);
    2819: }

    2821: /*@
    2822:   PetscDSGetDimensions - Returns the size of the approximation space for each field on an evaluation point

    2824:   Not collective

    2826:   Input Parameter:
    2827: . prob - The PetscDS object

    2829:   Output Parameter:
    2830: . dimensions - The number of dimensions

    2832:   Level: beginner

    2834: .seealso: PetscDSGetComponentOffsets(), PetscDSGetNumFields(), PetscDSCreate()
    2835: @*/
    2836: PetscErrorCode PetscDSGetDimensions(PetscDS prob, PetscInt *dimensions[])
    2837: {

    2842:   PetscDSSetUp(prob);
    2844:   *dimensions = prob->Nb;
    2845:   return(0);
    2846: }

    2848: /*@
    2849:   PetscDSGetComponents - Returns the number of components for each field on an evaluation point

    2851:   Not collective

    2853:   Input Parameter:
    2854: . prob - The PetscDS object

    2856:   Output Parameter:
    2857: . components - The number of components

    2859:   Level: beginner

    2861: .seealso: PetscDSGetComponentOffsets(), PetscDSGetNumFields(), PetscDSCreate()
    2862: @*/
    2863: PetscErrorCode PetscDSGetComponents(PetscDS prob, PetscInt *components[])
    2864: {

    2869:   PetscDSSetUp(prob);
    2871:   *components = prob->Nc;
    2872:   return(0);
    2873: }

    2875: /*@
    2876:   PetscDSGetComponentOffset - Returns the offset of the given field on an evaluation point

    2878:   Not collective

    2880:   Input Parameters:
    2881: + prob - The PetscDS object
    2882: - f - The field number

    2884:   Output Parameter:
    2885: . off - The offset

    2887:   Level: beginner

    2889: .seealso: PetscDSGetNumFields(), PetscDSCreate()
    2890: @*/
    2891: PetscErrorCode PetscDSGetComponentOffset(PetscDS prob, PetscInt f, PetscInt *off)
    2892: {
    2896:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    2897:   *off = prob->off[f];
    2898:   return(0);
    2899: }

    2901: /*@
    2902:   PetscDSGetComponentOffsets - Returns the offset of each field on an evaluation point

    2904:   Not collective

    2906:   Input Parameter:
    2907: . prob - The PetscDS object

    2909:   Output Parameter:
    2910: . offsets - The offsets

    2912:   Level: beginner

    2914: .seealso: PetscDSGetNumFields(), PetscDSCreate()
    2915: @*/
    2916: PetscErrorCode PetscDSGetComponentOffsets(PetscDS prob, PetscInt *offsets[])
    2917: {
    2921:   *offsets = prob->off;
    2922:   return(0);
    2923: }

    2925: /*@
    2926:   PetscDSGetComponentDerivativeOffsets - Returns the offset of each field derivative on an evaluation point

    2928:   Not collective

    2930:   Input Parameter:
    2931: . prob - The PetscDS object

    2933:   Output Parameter:
    2934: . offsets - The offsets

    2936:   Level: beginner

    2938: .seealso: PetscDSGetNumFields(), PetscDSCreate()
    2939: @*/
    2940: PetscErrorCode PetscDSGetComponentDerivativeOffsets(PetscDS prob, PetscInt *offsets[])
    2941: {
    2945:   *offsets = prob->offDer;
    2946:   return(0);
    2947: }

    2949: /*@C
    2950:   PetscDSGetTabulation - Return the basis tabulation at quadrature points for the volume discretization

    2952:   Not collective

    2954:   Input Parameter:
    2955: . prob - The PetscDS object

    2957:   Output Parameter:
    2958: . T - The basis function and derivatives tabulation at quadrature points for each field

    2960:   Level: intermediate

    2962: .seealso: PetscDSCreate()
    2963: @*/
    2964: PetscErrorCode PetscDSGetTabulation(PetscDS prob, PetscTabulation *T[])
    2965: {

    2971:   PetscDSSetUp(prob);
    2972:   *T = prob->T;
    2973:   return(0);
    2974: }

    2976: /*@C
    2977:   PetscDSGetFaceTabulation - Return the basis tabulation at quadrature points on the faces

    2979:   Not collective

    2981:   Input Parameter:
    2982: . prob - The PetscDS object

    2984:   Output Parameter:
    2985: . Tf - The basis function and derviative tabulation on each local face at quadrature points for each and field

    2987:   Level: intermediate

    2989: .seealso: PetscDSGetTabulation(), PetscDSCreate()
    2990: @*/
    2991: PetscErrorCode PetscDSGetFaceTabulation(PetscDS prob, PetscTabulation *Tf[])
    2992: {

    2998:   PetscDSSetUp(prob);
    2999:   *Tf = prob->Tf;
    3000:   return(0);
    3001: }

    3003: PetscErrorCode PetscDSGetEvaluationArrays(PetscDS prob, PetscScalar **u, PetscScalar **u_t, PetscScalar **u_x)
    3004: {

    3009:   PetscDSSetUp(prob);
    3013:   return(0);
    3014: }

    3016: PetscErrorCode PetscDSGetWeakFormArrays(PetscDS prob, PetscScalar **f0, PetscScalar **f1, PetscScalar **g0, PetscScalar **g1, PetscScalar **g2, PetscScalar **g3)
    3017: {

    3022:   PetscDSSetUp(prob);
    3029:   return(0);
    3030: }

    3032: PetscErrorCode PetscDSGetWorkspace(PetscDS prob, PetscReal **x, PetscScalar **basisReal, PetscScalar **basisDerReal, PetscScalar **testReal, PetscScalar **testDerReal)
    3033: {

    3038:   PetscDSSetUp(prob);
    3044:   return(0);
    3045: }

    3047: /*@C
    3048:   PetscDSAddBoundary - Add a boundary condition to the model. The pointwise functions are used to provide boundary values for essential boundary conditions. In FEM, they are acting upon by dual basis functionals to generate FEM coefficients which are fixed. Natural boundary conditions signal to PETSc that boundary integrals should be performaed, using the kernels from PetscDSSetBdResidual().

    3050:   Collective on ds

    3052:   Input Parameters:
    3053: + ds          - The PetscDS object
    3054: . type        - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
    3055: . name        - The BC name
    3056: . labelname   - The label defining constrained points
    3057: . field       - The field to constrain
    3058: . numcomps    - The number of constrained field components (0 will constrain all fields)
    3059: . comps       - An array of constrained component numbers
    3060: . bcFunc      - A pointwise function giving boundary values
    3061: . bcFunc_t    - A pointwise function giving the time derviative of the boundary values, or NULL
    3062: . numids      - The number of DMLabel ids for constrained points
    3063: . ids         - An array of ids for constrained points
    3064: - ctx         - An optional user context for bcFunc

    3066:   Options Database Keys:
    3067: + -bc_<boundary name> <num> - Overrides the boundary ids
    3068: - -bc_<boundary name>_comp <num> - Overrides the boundary components

    3070:   Note:
    3071:   Both bcFunc abd bcFunc_t will depend on the boundary condition type. If the type if DM_BC_ESSENTIAL, Then the calling sequence is:

    3073: $ bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])

    3075:   If the type is DM_BC_ESSENTIAL_FIELD or other _FIELD value, then the calling sequence is:

    3077: $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    3078: $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    3079: $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    3080: $        PetscReal time, const PetscReal x[], PetscScalar bcval[])

    3082: + dim - the spatial dimension
    3083: . Nf - the number of fields
    3084: . uOff - the offset into u[] and u_t[] for each field
    3085: . uOff_x - the offset into u_x[] for each field
    3086: . u - each field evaluated at the current point
    3087: . u_t - the time derivative of each field evaluated at the current point
    3088: . u_x - the gradient of each field evaluated at the current point
    3089: . aOff - the offset into a[] and a_t[] for each auxiliary field
    3090: . aOff_x - the offset into a_x[] for each auxiliary field
    3091: . a - each auxiliary field evaluated at the current point
    3092: . a_t - the time derivative of each auxiliary field evaluated at the current point
    3093: . a_x - the gradient of auxiliary each field evaluated at the current point
    3094: . t - current time
    3095: . x - coordinates of the current point
    3096: . numConstants - number of constant parameters
    3097: . constants - constant parameters
    3098: - bcval - output values at the current point

    3100:   Level: developer

    3102: .seealso: PetscDSGetBoundary(), PetscDSSetResidual(), PetscDSSetBdResidual()
    3103: @*/
    3104: PetscErrorCode PetscDSAddBoundary(PetscDS ds, DMBoundaryConditionType type, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(void), void (*bcFunc_t)(void), PetscInt numids, const PetscInt *ids, void *ctx)
    3105: {
    3106:   DSBoundary     b;

    3115:   PetscNew(&b);
    3116:   PetscStrallocpy(name, (char **) &b->name);
    3117:   PetscStrallocpy(labelname, (char **) &b->labelname);
    3118:   PetscMalloc1(numcomps, &b->comps);
    3119:   if (numcomps) {PetscArraycpy(b->comps, comps, numcomps);}
    3120:   PetscMalloc1(numids, &b->ids);
    3121:   if (numids) {PetscArraycpy(b->ids, ids, numids);}
    3122:   b->type            = type;
    3123:   b->field           = field;
    3124:   b->numcomps        = numcomps;
    3125:   b->func            = bcFunc;
    3126:   b->func_t          = bcFunc_t;
    3127:   b->numids          = numids;
    3128:   b->ctx             = ctx;
    3129:   b->next            = ds->boundary;
    3130:   ds->boundary       = b;
    3131:   return(0);
    3132: }

    3134: /*@C
    3135:   PetscDSUpdateBoundary - Change a boundary condition for the model. The pointwise functions are used to provide boundary values for essential boundary conditions. In FEM, they are acting upon by dual basis functionals to generate FEM coefficients which are fixed. Natural boundary conditions signal to PETSc that boundary integrals should be performaed, using the kernels from PetscDSSetBdResidual().

    3137:   Input Parameters:
    3138: + ds          - The PetscDS object
    3139: . bd          - The boundary condition number
    3140: . type        - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
    3141: . name        - The BC name
    3142: . labelname   - The label defining constrained points
    3143: . field       - The field to constrain
    3144: . numcomps    - The number of constrained field components
    3145: . comps       - An array of constrained component numbers
    3146: . bcFunc      - A pointwise function giving boundary values
    3147: . bcFunc_t    - A pointwise function giving the time derviative of the boundary values, or NULL
    3148: . numids      - The number of DMLabel ids for constrained points
    3149: . ids         - An array of ids for constrained points
    3150: - ctx         - An optional user context for bcFunc

    3152:   Note:
    3153:   The boundary condition number is the order in which it was registered. The user can get the number of boundary conditions from PetscDSGetNumBoundary(). See PetscDSAddBoundary() for a description of the calling sequences for the callbacks.

    3155:   Level: developer

    3157: .seealso: PetscDSAddBoundary(), PetscDSGetBoundary(), PetscDSGetNumBoundary()
    3158: @*/
    3159: PetscErrorCode PetscDSUpdateBoundary(PetscDS ds, PetscInt bd, DMBoundaryConditionType type, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(void), void (*bcFunc_t)(void), PetscInt numids, const PetscInt *ids, void *ctx)
    3160: {
    3161:   DSBoundary     b = ds->boundary;
    3162:   PetscInt       n = 0;

    3167:   while (b) {
    3168:     if (n == bd) break;
    3169:     b = b->next;
    3170:     ++n;
    3171:   }
    3172:   if (!b) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n);
    3173:   if (name) {
    3174:     PetscFree(b->name);
    3175:     PetscStrallocpy(name, (char **) &b->name);
    3176:   }
    3177:   if (labelname) {
    3178:     PetscFree(b->labelname);
    3179:     PetscStrallocpy(labelname, (char **) &b->labelname);
    3180:   }
    3181:   if (numcomps >= 0 && numcomps != b->numcomps) {
    3182:     b->numcomps = numcomps;
    3183:     PetscFree(b->comps);
    3184:     PetscMalloc1(numcomps, &b->comps);
    3185:     if (numcomps) {PetscArraycpy(b->comps, comps, numcomps);}
    3186:   }
    3187:   if (numids >= 0 && numids != b->numids) {
    3188:     b->numids = numids;
    3189:     PetscFree(b->ids);
    3190:     PetscMalloc1(numids, &b->ids);
    3191:     if (numids) {PetscArraycpy(b->ids, ids, numids);}
    3192:   }
    3193:   b->type = type;
    3194:   if (field >= 0) {b->field  = field;}
    3195:   if (bcFunc)     {b->func   = bcFunc;}
    3196:   if (bcFunc_t)   {b->func_t = bcFunc_t;}
    3197:   if (ctx)        {b->ctx    = ctx;}
    3198:   return(0);
    3199: }

    3201: /*@
    3202:   PetscDSGetNumBoundary - Get the number of registered BC

    3204:   Input Parameters:
    3205: . ds - The PetscDS object

    3207:   Output Parameters:
    3208: . numBd - The number of BC

    3210:   Level: intermediate

    3212: .seealso: PetscDSAddBoundary(), PetscDSGetBoundary()
    3213: @*/
    3214: PetscErrorCode PetscDSGetNumBoundary(PetscDS ds, PetscInt *numBd)
    3215: {
    3216:   DSBoundary b = ds->boundary;

    3221:   *numBd = 0;
    3222:   while (b) {++(*numBd); b = b->next;}
    3223:   return(0);
    3224: }

    3226: /*@C
    3227:   PetscDSGetBoundary - Gets a boundary condition to the model

    3229:   Input Parameters:
    3230: + ds          - The PetscDS object
    3231: - bd          - The BC number

    3233:   Output Parameters:
    3234: + type        - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
    3235: . name        - The BC name
    3236: . labelname   - The label defining constrained points
    3237: . field       - The field to constrain
    3238: . numcomps    - The number of constrained field components
    3239: . comps       - An array of constrained component numbers
    3240: . bcFunc      - A pointwise function giving boundary values
    3241: . bcFunc_t    - A pointwise function giving the time derviative of the boundary values
    3242: . numids      - The number of DMLabel ids for constrained points
    3243: . ids         - An array of ids for constrained points
    3244: - ctx         - An optional user context for bcFunc

    3246:   Options Database Keys:
    3247: + -bc_<boundary name> <num> - Overrides the boundary ids
    3248: - -bc_<boundary name>_comp <num> - Overrides the boundary components

    3250:   Level: developer

    3252: .seealso: PetscDSAddBoundary()
    3253: @*/
    3254: PetscErrorCode PetscDSGetBoundary(PetscDS ds, PetscInt bd, DMBoundaryConditionType *type, const char **name, const char **labelname, PetscInt *field, PetscInt *numcomps, const PetscInt **comps, void (**func)(void), void (**func_t)(void), PetscInt *numids, const PetscInt **ids, void **ctx)
    3255: {
    3256:   DSBoundary b    = ds->boundary;
    3257:   PetscInt   n    = 0;

    3261:   while (b) {
    3262:     if (n == bd) break;
    3263:     b = b->next;
    3264:     ++n;
    3265:   }
    3266:   if (!b) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n);
    3267:   if (type) {
    3269:     *type = b->type;
    3270:   }
    3271:   if (name) {
    3273:     *name = b->name;
    3274:   }
    3275:   if (labelname) {
    3277:     *labelname = b->labelname;
    3278:   }
    3279:   if (field) {
    3281:     *field = b->field;
    3282:   }
    3283:   if (numcomps) {
    3285:     *numcomps = b->numcomps;
    3286:   }
    3287:   if (comps) {
    3289:     *comps = b->comps;
    3290:   }
    3291:   if (func) {
    3293:     *func = b->func;
    3294:   }
    3295:   if (func_t) {
    3297:     *func_t = b->func_t;
    3298:   }
    3299:   if (numids) {
    3301:     *numids = b->numids;
    3302:   }
    3303:   if (ids) {
    3305:     *ids = b->ids;
    3306:   }
    3307:   if (ctx) {
    3309:     *ctx = b->ctx;
    3310:   }
    3311:   return(0);
    3312: }

    3314: /*@
    3315:   PetscDSCopyBoundary - Copy all boundary condition objects to the new problem

    3317:   Not collective

    3319:   Input Parameter:
    3320: . prob - The PetscDS object

    3322:   Output Parameter:
    3323: . newprob - The PetscDS copy

    3325:   Level: intermediate

    3327: .seealso: PetscDSCopyEquations(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
    3328: @*/
    3329: PetscErrorCode PetscDSCopyBoundary(PetscDS probA, PetscDS probB)
    3330: {
    3331:   DSBoundary     b, next, *lastnext;

    3337:   if (probA == probB) return(0);
    3338:   next = probB->boundary;
    3339:   while (next) {
    3340:     DSBoundary b = next;

    3342:     next = b->next;
    3343:     PetscFree(b->comps);
    3344:     PetscFree(b->ids);
    3345:     PetscFree(b->name);
    3346:     PetscFree(b->labelname);
    3347:     PetscFree(b);
    3348:   }
    3349:   lastnext = &(probB->boundary);
    3350:   for (b = probA->boundary; b; b = b->next) {
    3351:     DSBoundary bNew;

    3353:     PetscNew(&bNew);
    3354:     bNew->numcomps = b->numcomps;
    3355:     PetscMalloc1(bNew->numcomps, &bNew->comps);
    3356:     PetscArraycpy(bNew->comps, b->comps, bNew->numcomps);
    3357:     bNew->numids = b->numids;
    3358:     PetscMalloc1(bNew->numids, &bNew->ids);
    3359:     PetscArraycpy(bNew->ids, b->ids, bNew->numids);
    3360:     PetscStrallocpy(b->labelname,(char **) &(bNew->labelname));
    3361:     PetscStrallocpy(b->name,(char **) &(bNew->name));
    3362:     bNew->ctx   = b->ctx;
    3363:     bNew->type  = b->type;
    3364:     bNew->field = b->field;
    3365:     bNew->func  = b->func;

    3367:     *lastnext = bNew;
    3368:     lastnext = &(bNew->next);
    3369:   }
    3370:   return(0);
    3371: }

    3373: /*@
    3374:   PetscDSSelectDiscretizations - Copy discretizations to the new problem with different field layout

    3376:   Not collective

    3378:   Input Parameter:
    3379: + prob - The PetscDS object
    3380: . numFields - Number of new fields
    3381: - fields - Old field number for each new field

    3383:   Output Parameter:
    3384: . newprob - The PetscDS copy

    3386:   Level: intermediate

    3388: .seealso: PetscDSSelectEquations(), PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
    3389: @*/
    3390: PetscErrorCode PetscDSSelectDiscretizations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob)
    3391: {
    3392:   PetscInt       Nf, Nfn, fn;

    3399:   PetscDSGetNumFields(prob, &Nf);
    3400:   PetscDSGetNumFields(newprob, &Nfn);
    3401:   if (numFields > Nfn) SETERRQ2(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_SIZ, "Number of fields %D to transfer must not be greater then the total number of fields %D", numFields, Nfn);
    3402:   for (fn = 0; fn < numFields; ++fn) {
    3403:     const PetscInt f = fields ? fields[fn] : fn;
    3404:     PetscObject    disc;

    3406:     if (f >= Nf) continue;
    3407:     PetscDSGetDiscretization(prob, f, &disc);
    3408:     PetscDSSetDiscretization(newprob, fn, disc);
    3409:   }
    3410:   return(0);
    3411: }

    3413: /*@
    3414:   PetscDSSelectEquations - Copy pointwise function pointers to the new problem with different field layout

    3416:   Not collective

    3418:   Input Parameter:
    3419: + prob - The PetscDS object
    3420: . numFields - Number of new fields
    3421: - fields - Old field number for each new field

    3423:   Output Parameter:
    3424: . newprob - The PetscDS copy

    3426:   Level: intermediate

    3428: .seealso: PetscDSSelectDiscretizations(), PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
    3429: @*/
    3430: PetscErrorCode PetscDSSelectEquations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob)
    3431: {
    3432:   PetscInt       Nf, Nfn, fn, gn;

    3439:   PetscDSGetNumFields(prob, &Nf);
    3440:   PetscDSGetNumFields(newprob, &Nfn);
    3441:   if (numFields > Nfn) SETERRQ2(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_SIZ, "Number of fields %D to transfer must not be greater then the total number of fields %D", numFields, Nfn);
    3442:   for (fn = 0; fn < numFields; ++fn) {
    3443:     const PetscInt   f = fields ? fields[fn] : fn;
    3444:     PetscPointFunc   obj;
    3445:     PetscPointFunc   f0, f1;
    3446:     PetscBdPointFunc f0Bd, f1Bd;
    3447:     PetscRiemannFunc r;

    3449:     if (f >= Nf) continue;
    3450:     PetscDSGetObjective(prob, f, &obj);
    3451:     PetscDSGetResidual(prob, f, &f0, &f1);
    3452:     PetscDSGetBdResidual(prob, f, &f0Bd, &f1Bd);
    3453:     PetscDSGetRiemannSolver(prob, f, &r);
    3454:     PetscDSSetObjective(newprob, fn, obj);
    3455:     PetscDSSetResidual(newprob, fn, f0, f1);
    3456:     PetscDSSetBdResidual(newprob, fn, f0Bd, f1Bd);
    3457:     PetscDSSetRiemannSolver(newprob, fn, r);
    3458:     for (gn = 0; gn < numFields; ++gn) {
    3459:       const PetscInt  g = fields ? fields[gn] : gn;
    3460:       PetscPointJac   g0, g1, g2, g3;
    3461:       PetscPointJac   g0p, g1p, g2p, g3p;
    3462:       PetscBdPointJac g0Bd, g1Bd, g2Bd, g3Bd;

    3464:       if (g >= Nf) continue;
    3465:       PetscDSGetJacobian(prob, f, g, &g0, &g1, &g2, &g3);
    3466:       PetscDSGetJacobianPreconditioner(prob, f, g, &g0p, &g1p, &g2p, &g3p);
    3467:       PetscDSGetBdJacobian(prob, f, g, &g0Bd, &g1Bd, &g2Bd, &g3Bd);
    3468:       PetscDSSetJacobian(newprob, fn, gn, g0, g1, g2, g3);
    3469:       PetscDSSetJacobianPreconditioner(newprob, fn, gn, g0p, g1p, g2p, g3p);
    3470:       PetscDSSetBdJacobian(newprob, fn, gn, g0Bd, g1Bd, g2Bd, g3Bd);
    3471:     }
    3472:   }
    3473:   return(0);
    3474: }

    3476: /*@
    3477:   PetscDSCopyEquations - Copy all pointwise function pointers to the new problem

    3479:   Not collective

    3481:   Input Parameter:
    3482: . prob - The PetscDS object

    3484:   Output Parameter:
    3485: . newprob - The PetscDS copy

    3487:   Level: intermediate

    3489: .seealso: PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
    3490: @*/
    3491: PetscErrorCode PetscDSCopyEquations(PetscDS prob, PetscDS newprob)
    3492: {
    3493:   PetscInt       Nf, Ng;

    3499:   PetscDSGetNumFields(prob, &Nf);
    3500:   PetscDSGetNumFields(newprob, &Ng);
    3501:   if (Nf != Ng) SETERRQ2(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_SIZ, "Number of fields must match %D != %D", Nf, Ng);
    3502:   PetscDSSelectEquations(prob, Nf, NULL, newprob);
    3503:   return(0);
    3504: }
    3505: /*@
    3506:   PetscDSCopyConstants - Copy all constants to the new problem

    3508:   Not collective

    3510:   Input Parameter:
    3511: . prob - The PetscDS object

    3513:   Output Parameter:
    3514: . newprob - The PetscDS copy

    3516:   Level: intermediate

    3518: .seealso: PetscDSCopyBoundary(), PetscDSCopyEquations(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
    3519: @*/
    3520: PetscErrorCode PetscDSCopyConstants(PetscDS prob, PetscDS newprob)
    3521: {
    3522:   PetscInt           Nc;
    3523:   const PetscScalar *constants;
    3524:   PetscErrorCode     ierr;

    3529:   PetscDSGetConstants(prob, &Nc, &constants);
    3530:   PetscDSSetConstants(newprob, Nc, (PetscScalar *) constants);
    3531:   return(0);
    3532: }

    3534: PetscErrorCode PetscDSGetHeightSubspace(PetscDS prob, PetscInt height, PetscDS *subprob)
    3535: {
    3536:   PetscInt       dim, Nf, f;

    3542:   if (height == 0) {*subprob = prob; return(0);}
    3543:   PetscDSGetNumFields(prob, &Nf);
    3544:   PetscDSGetSpatialDimension(prob, &dim);
    3545:   if (height > dim) SETERRQ2(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_OUTOFRANGE, "DS can only handle height in [0, %D], not %D", dim, height);
    3546:   if (!prob->subprobs) {PetscCalloc1(dim, &prob->subprobs);}
    3547:   if (!prob->subprobs[height-1]) {
    3548:     PetscInt cdim;

    3550:     PetscDSCreate(PetscObjectComm((PetscObject) prob), &prob->subprobs[height-1]);
    3551:     PetscDSGetCoordinateDimension(prob, &cdim);
    3552:     PetscDSSetCoordinateDimension(prob->subprobs[height-1], cdim);
    3553:     for (f = 0; f < Nf; ++f) {
    3554:       PetscFE      subfe;
    3555:       PetscObject  obj;
    3556:       PetscClassId id;

    3558:       PetscDSGetDiscretization(prob, f, &obj);
    3559:       PetscObjectGetClassId(obj, &id);
    3560:       if (id == PETSCFE_CLASSID) {PetscFEGetHeightSubspace((PetscFE) obj, height, &subfe);}
    3561:       else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unsupported discretization type for field %d", f);
    3562:       PetscDSSetDiscretization(prob->subprobs[height-1], f, (PetscObject) subfe);
    3563:     }
    3564:   }
    3565:   *subprob = prob->subprobs[height-1];
    3566:   return(0);
    3567: }

    3569: PetscErrorCode PetscDSGetDiscType_Internal(PetscDS ds, PetscInt f, PetscDiscType *disctype)
    3570: {
    3571:   PetscObject    obj;
    3572:   PetscClassId   id;
    3573:   PetscInt       Nf;

    3579:   *disctype = PETSC_DISC_NONE;
    3580:   PetscDSGetNumFields(ds, &Nf);
    3581:   if (f >= Nf) SETERRQ2(PetscObjectComm((PetscObject) ds), PETSC_ERR_ARG_SIZ, "Field %D must be in [0, %D)", f, Nf);
    3582:   PetscDSGetDiscretization(ds, f, &obj);
    3583:   if (obj) {
    3584:     PetscObjectGetClassId(obj, &id);
    3585:     if (id == PETSCFE_CLASSID) *disctype = PETSC_DISC_FE;
    3586:     else                       *disctype = PETSC_DISC_FV;
    3587:   }
    3588:   return(0);
    3589: }

    3591: static PetscErrorCode PetscDSDestroy_Basic(PetscDS prob)
    3592: {
    3593:   PetscErrorCode      ierr;

    3596:   PetscFree(prob->data);
    3597:   return(0);
    3598: }

    3600: static PetscErrorCode PetscDSInitialize_Basic(PetscDS prob)
    3601: {
    3603:   prob->ops->setfromoptions = NULL;
    3604:   prob->ops->setup          = NULL;
    3605:   prob->ops->view           = NULL;
    3606:   prob->ops->destroy        = PetscDSDestroy_Basic;
    3607:   return(0);
    3608: }

    3610: /*MC
    3611:   PETSCDSBASIC = "basic" - A discrete system with pointwise residual and boundary residual functions

    3613:   Level: intermediate

    3615: .seealso: PetscDSType, PetscDSCreate(), PetscDSSetType()
    3616: M*/

    3618: PETSC_EXTERN PetscErrorCode PetscDSCreate_Basic(PetscDS prob)
    3619: {
    3620:   PetscDS_Basic *b;
    3621:   PetscErrorCode      ierr;

    3625:   PetscNewLog(prob, &b);
    3626:   prob->data = b;

    3628:   PetscDSInitialize_Basic(prob);
    3629:   return(0);
    3630: }