Date: 2022-08-02T03:14:27+00:00

Actual source code: dtds.c

      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: {
     57:   PetscFunctionListAdd(&PetscDSList, sname, function);
     58:   return 0;
     59: }

     61: /*@C
     62:   PetscDSSetType - Builds a particular PetscDS

     64:   Collective on prob

     66:   Input Parameters:
     67: + prob - The PetscDS object
     68: - name - The kind of system

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

     73:   Level: intermediate

     75:    Not available from Fortran

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

     85:   PetscObjectTypeCompare((PetscObject) prob, name, &match);
     86:   if (match) return 0;

     88:   PetscDSRegisterAll();
     89:   PetscFunctionListFind(PetscDSList, name, &r);

     92:   if (prob->ops->destroy) {
     93:     (*prob->ops->destroy)(prob);
     94:     prob->ops->destroy = NULL;
     95:   }
     96:   (*r)(prob);
     97:   PetscObjectChangeTypeName((PetscObject) prob, name);
     98:   return 0;
     99: }

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

    104:   Not Collective

    106:   Input Parameter:
    107: . prob  - The PetscDS

    109:   Output Parameter:
    110: . name - The PetscDS type name

    112:   Level: intermediate

    114:    Not available from Fortran

    116: .seealso: PetscDSSetType(), PetscDSCreate()
    117: @*/
    118: PetscErrorCode PetscDSGetType(PetscDS prob, PetscDSType *name)
    119: {
    122:   PetscDSRegisterAll();
    123:   *name = ((PetscObject) prob)->type_name;
    124:   return 0;
    125: }

    127: static PetscErrorCode PetscDSView_Ascii(PetscDS ds, PetscViewer viewer)
    128: {
    129:   PetscViewerFormat  format;
    130:   const PetscScalar *constants;
    131:   PetscInt           Nf, numConstants, f;

    133:   PetscDSGetNumFields(ds, &Nf);
    134:   PetscViewerGetFormat(viewer, &format);
    135:   PetscViewerASCIIPrintf(viewer, "Discrete System with %d fields\n", Nf);
    136:   PetscViewerASCIIPushTab(viewer);
    137:   PetscViewerASCIIPrintf(viewer, "  cell total dim %D total comp %D\n", ds->totDim, ds->totComp);
    138:   if (ds->isCohesive) PetscViewerASCIIPrintf(viewer, "  cohesive cell\n");
    139:   for (f = 0; f < Nf; ++f) {
    140:     DSBoundary      b;
    141:     PetscObject     obj;
    142:     PetscClassId    id;
    143:     PetscQuadrature q;
    144:     const char     *name;
    145:     PetscInt        Nc, Nq, Nqc;

    147:     PetscDSGetDiscretization(ds, f, &obj);
    148:     PetscObjectGetClassId(obj, &id);
    149:     PetscObjectGetName(obj, &name);
    150:     PetscViewerASCIIPrintf(viewer, "Field %s", name ? name : "<unknown>");
    151:     PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);
    152:     if (id == PETSCFE_CLASSID)      {
    153:       PetscFEGetNumComponents((PetscFE) obj, &Nc);
    154:       PetscFEGetQuadrature((PetscFE) obj, &q);
    155:       PetscViewerASCIIPrintf(viewer, " FEM");
    156:     } else if (id == PETSCFV_CLASSID) {
    157:       PetscFVGetNumComponents((PetscFV) obj, &Nc);
    158:       PetscFVGetQuadrature((PetscFV) obj, &q);
    159:       PetscViewerASCIIPrintf(viewer, " FVM");
    160:     }
    161:     else SETERRQ(PetscObjectComm((PetscObject) ds), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %D", f);
    162:     if (Nc > 1) PetscViewerASCIIPrintf(viewer, " %D components", Nc);
    163:     else        PetscViewerASCIIPrintf(viewer, " %D component ", Nc);
    164:     if (ds->implicit[f]) PetscViewerASCIIPrintf(viewer, " (implicit)");
    165:     else                 PetscViewerASCIIPrintf(viewer, " (explicit)");
    166:     if (q) {
    167:       PetscQuadratureGetData(q, NULL, &Nqc, &Nq, NULL, NULL);
    168:       PetscViewerASCIIPrintf(viewer, " (Nq %D Nqc %D)", Nq, Nqc);
    169:     }
    170:     PetscViewerASCIIPrintf(viewer, " %D-jet", ds->jetDegree[f]);
    171:     PetscViewerASCIIPrintf(viewer, "\n");
    172:     PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);
    173:     PetscViewerASCIIPushTab(viewer);
    174:     if (id == PETSCFE_CLASSID)      PetscFEView((PetscFE) obj, viewer);
    175:     else if (id == PETSCFV_CLASSID) PetscFVView((PetscFV) obj, viewer);
    176:     PetscViewerASCIIPopTab(viewer);

    178:     for (b = ds->boundary; b; b = b->next) {
    179:       char     *name;
    180:       PetscInt  c, i;

    182:       if (b->field != f) continue;
    183:       PetscViewerASCIIPushTab(viewer);
    184:       PetscViewerASCIIPrintf(viewer, "Boundary %s (%s) %s\n", b->name, b->lname, DMBoundaryConditionTypes[b->type]);
    185:       if (!b->Nc) {
    186:         PetscViewerASCIIPrintf(viewer, "  all components\n");
    187:       } else {
    188:         PetscViewerASCIIPrintf(viewer, "  components: ");
    189:         PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);
    190:         for (c = 0; c < b->Nc; ++c) {
    191:           if (c > 0) PetscViewerASCIIPrintf(viewer, ", ");
    192:           PetscViewerASCIIPrintf(viewer, "%D", b->comps[c]);
    193:         }
    194:         PetscViewerASCIIPrintf(viewer, "\n");
    195:         PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);
    196:       }
    197:       PetscViewerASCIIPrintf(viewer, "  values: ");
    198:       PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);
    199:       for (i = 0; i < b->Nv; ++i) {
    200:         if (i > 0) PetscViewerASCIIPrintf(viewer, ", ");
    201:         PetscViewerASCIIPrintf(viewer, "%D", b->values[i]);
    202:       }
    203:       PetscViewerASCIIPrintf(viewer, "\n");
    204:       PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);
    205:       if (b->func) {
    206:         PetscDLAddr(b->func, &name);
    207:         if (name) PetscViewerASCIIPrintf(viewer, "  func: %s\n", name);
    208:         else      PetscViewerASCIIPrintf(viewer, "  func: %p\n", b->func);
    209:         PetscFree(name);
    210:       }
    211:       if (b->func_t) {
    212:         PetscDLAddr(b->func_t, &name);
    213:         if (name) PetscViewerASCIIPrintf(viewer, "  func_t: %s\n", name);
    214:         else      PetscViewerASCIIPrintf(viewer, "  func_t: %p\n", b->func_t);
    215:         PetscFree(name);
    216:       }
    217:       PetscWeakFormView(b->wf, viewer);
    218:       PetscViewerASCIIPopTab(viewer);
    219:     }
    220:   }
    221:   PetscDSGetConstants(ds, &numConstants, &constants);
    222:   if (numConstants) {
    223:     PetscViewerASCIIPrintf(viewer, "%D constants\n", numConstants);
    224:     PetscViewerASCIIPushTab(viewer);
    225:     for (f = 0; f < numConstants; ++f) PetscViewerASCIIPrintf(viewer, "%g\n", (double) PetscRealPart(constants[f]));
    226:     PetscViewerASCIIPopTab(viewer);
    227:   }
    228:   PetscWeakFormView(ds->wf, viewer);
    229:   PetscViewerASCIIPopTab(viewer);
    230:   return 0;
    231: }

    233: /*@C
    234:    PetscDSViewFromOptions - View from Options

    236:    Collective on PetscDS

    238:    Input Parameters:
    239: +  A - the PetscDS object
    240: .  obj - Optional object
    241: -  name - command line option

    243:    Level: intermediate
    244: .seealso:  PetscDS, PetscDSView, PetscObjectViewFromOptions(), PetscDSCreate()
    245: @*/
    246: PetscErrorCode  PetscDSViewFromOptions(PetscDS A,PetscObject obj,const char name[])
    247: {
    249:   PetscObjectViewFromOptions((PetscObject)A,obj,name);
    250:   return 0;
    251: }

    253: /*@C
    254:   PetscDSView - Views a PetscDS

    256:   Collective on prob

    258:   Input Parameters:
    259: + prob - the PetscDS object to view
    260: - v  - the viewer

    262:   Level: developer

    264: .seealso PetscDSDestroy()
    265: @*/
    266: PetscErrorCode PetscDSView(PetscDS prob, PetscViewer v)
    267: {
    268:   PetscBool      iascii;

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

    279: /*@
    280:   PetscDSSetFromOptions - sets parameters in a PetscDS from the options database

    282:   Collective on prob

    284:   Input Parameter:
    285: . prob - the PetscDS object to set options for

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

    294:   Level: developer

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

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

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

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

    356: /*@C
    357:   PetscDSSetUp - Construct data structures for the PetscDS

    359:   Collective on prob

    361:   Input Parameter:
    362: . prob - the PetscDS object to setup

    364:   Level: developer

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

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

    391:     PetscDSGetDiscretization(prob, f, &obj);
    392:     if (prob->jetDegree[f] > 1) hasH = PETSC_TRUE;
    393:     if (!obj) {
    394:       /* Empty mesh */
    395:       Nb = Nc = 0;
    396:       prob->T[f] = prob->Tf[f] = NULL;
    397:     } else {
    398:       PetscObjectGetClassId(obj, &id);
    399:       if (id == PETSCFE_CLASSID)      {
    400:         PetscFE fe = (PetscFE) obj;

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

    410:         PetscFVGetQuadrature(fv, &q);
    411:         PetscFVGetNumComponents(fv, &Nc);
    412:         Nb   = Nc;
    413:         PetscFVGetCellTabulation(fv, &prob->T[f]);
    414:         /* TODO: should PetscFV also have face tabulation? Otherwise there will be a null pointer in prob->basisFace */
    415:       } else SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f);
    416:     }
    417:     prob->Nc[f]       = Nc;
    418:     prob->Nb[f]       = Nb;
    419:     prob->off[f+1]    = Nc     + prob->off[f];
    420:     prob->offDer[f+1] = Nc*dim + prob->offDer[f];
    421:     prob->offCohesive[0][f+1]    = (prob->cohesive[f] ? Nc : Nc*2)          + prob->offCohesive[0][f];
    422:     prob->offDerCohesive[0][f+1] = (prob->cohesive[f] ? Nc : Nc*2)*dimEmbed + prob->offDerCohesive[0][f];
    423:     prob->offCohesive[1][f]      = (prob->cohesive[f] ? 0 : Nc)             + prob->offCohesive[0][f];
    424:     prob->offDerCohesive[1][f]   = (prob->cohesive[f] ? 0 : Nc)*dimEmbed    + prob->offDerCohesive[0][f];
    425:     prob->offCohesive[2][f+1]    = (prob->cohesive[f] ? Nc : Nc*2)          + prob->offCohesive[2][f];
    426:     prob->offDerCohesive[2][f+1] = (prob->cohesive[f] ? Nc : Nc*2)*dimEmbed + prob->offDerCohesive[2][f];
    427:     if (q) PetscQuadratureGetData(q, NULL, NULL, &Nq, NULL, NULL);
    428:     NqMax          = PetscMax(NqMax, Nq);
    429:     NbMax          = PetscMax(NbMax, Nb);
    430:     NcMax          = PetscMax(NcMax, Nc);
    431:     prob->totDim  += Nb;
    432:     prob->totComp += Nc;
    433:     /* There are two faces for all fields on a cohesive cell, except for cohesive fields */
    434:     if (prob->isCohesive && !prob->cohesive[f]) prob->totDim += Nb;
    435:   }
    436:   prob->offCohesive[1][Nf]    = prob->offCohesive[0][Nf];
    437:   prob->offDerCohesive[1][Nf] = prob->offDerCohesive[0][Nf];
    438:   /* Allocate works space */
    439:   NsMax = 2; /* A non-cohesive discretizations can be used on a cohesive cell, so we need this extra workspace for all DS */
    440:   PetscMalloc3(NsMax*prob->totComp,&prob->u,NsMax*prob->totComp,&prob->u_t,NsMax*prob->totComp*dimEmbed + (hasH ? NsMax*prob->totComp*dimEmbed*dimEmbed : 0),&prob->u_x);
    441:   PetscMalloc5(dimEmbed,&prob->x,NbMax*NcMax,&prob->basisReal,NbMax*NcMax*dimEmbed,&prob->basisDerReal,NbMax*NcMax,&prob->testReal,NbMax*NcMax*dimEmbed,&prob->testDerReal);
    442:   PetscMalloc6(NsMax*NqMax*NcMax,&prob->f0,NsMax*NqMax*NcMax*dimEmbed,&prob->f1,
    443:                       NsMax*NsMax*NqMax*NcMax*NcMax,&prob->g0,NsMax*NsMax*NqMax*NcMax*NcMax*dimEmbed,&prob->g1,
    444:                       NsMax*NsMax*NqMax*NcMax*NcMax*dimEmbed,&prob->g2,NsMax*NsMax*NqMax*NcMax*NcMax*dimEmbed*dimEmbed,&prob->g3);
    445:   if (prob->ops->setup) (*prob->ops->setup)(prob);
    446:   prob->setup = PETSC_TRUE;
    447:   return 0;
    448: }

    450: static PetscErrorCode PetscDSDestroyStructs_Static(PetscDS prob)
    451: {
    452:   PetscFree2(prob->Nc,prob->Nb);
    453:   PetscFree2(prob->off,prob->offDer);
    454:   PetscFree6(prob->offCohesive[0],prob->offCohesive[1],prob->offCohesive[2],prob->offDerCohesive[0],prob->offDerCohesive[1],prob->offDerCohesive[2]);
    455:   PetscFree2(prob->T,prob->Tf);
    456:   PetscFree3(prob->u,prob->u_t,prob->u_x);
    457:   PetscFree5(prob->x,prob->basisReal, prob->basisDerReal,prob->testReal,prob->testDerReal);
    458:   PetscFree6(prob->f0,prob->f1,prob->g0,prob->g1,prob->g2,prob->g3);
    459:   return 0;
    460: }

    462: static PetscErrorCode PetscDSEnlarge_Static(PetscDS prob, PetscInt NfNew)
    463: {
    464:   PetscObject      *tmpd;
    465:   PetscBool        *tmpi;
    466:   PetscInt         *tmpk;
    467:   PetscBool        *tmpc;
    468:   PetscPointFunc   *tmpup;
    469:   PetscSimplePointFunc *tmpexactSol,  *tmpexactSol_t;
    470:   void                **tmpexactCtx, **tmpexactCtx_t;
    471:   void            **tmpctx;
    472:   PetscInt          Nf = prob->Nf, f;

    474:   if (Nf >= NfNew) return 0;
    475:   prob->setup = PETSC_FALSE;
    476:   PetscDSDestroyStructs_Static(prob);
    477:   PetscMalloc4(NfNew, &tmpd, NfNew, &tmpi, NfNew, &tmpc, NfNew, &tmpk);
    478:   for (f = 0; f < Nf; ++f) {tmpd[f] = prob->disc[f]; tmpi[f] = prob->implicit[f]; tmpc[f] = prob->cohesive[f]; tmpk[f] = prob->jetDegree[f];}
    479:   for (f = Nf; f < NfNew; ++f) {tmpd[f] = NULL; tmpi[f] = PETSC_TRUE, tmpc[f] = PETSC_FALSE; tmpk[f] = 1;}
    480:   PetscFree4(prob->disc, prob->implicit, prob->cohesive, prob->jetDegree);
    481:   PetscWeakFormSetNumFields(prob->wf, NfNew);
    482:   prob->Nf        = NfNew;
    483:   prob->disc      = tmpd;
    484:   prob->implicit  = tmpi;
    485:   prob->cohesive  = tmpc;
    486:   prob->jetDegree = tmpk;
    487:   PetscCalloc2(NfNew, &tmpup, NfNew, &tmpctx);
    488:   for (f = 0; f < Nf; ++f) tmpup[f] = prob->update[f];
    489:   for (f = 0; f < Nf; ++f) tmpctx[f] = prob->ctx[f];
    490:   for (f = Nf; f < NfNew; ++f) tmpup[f] = NULL;
    491:   for (f = Nf; f < NfNew; ++f) tmpctx[f] = NULL;
    492:   PetscFree2(prob->update, prob->ctx);
    493:   prob->update = tmpup;
    494:   prob->ctx = tmpctx;
    495:   PetscCalloc4(NfNew, &tmpexactSol, NfNew, &tmpexactCtx, NfNew, &tmpexactSol_t, NfNew, &tmpexactCtx_t);
    496:   for (f = 0; f < Nf; ++f) tmpexactSol[f] = prob->exactSol[f];
    497:   for (f = 0; f < Nf; ++f) tmpexactCtx[f] = prob->exactCtx[f];
    498:   for (f = 0; f < Nf; ++f) tmpexactSol_t[f] = prob->exactSol_t[f];
    499:   for (f = 0; f < Nf; ++f) tmpexactCtx_t[f] = prob->exactCtx_t[f];
    500:   for (f = Nf; f < NfNew; ++f) tmpexactSol[f] = NULL;
    501:   for (f = Nf; f < NfNew; ++f) tmpexactCtx[f] = NULL;
    502:   for (f = Nf; f < NfNew; ++f) tmpexactSol_t[f] = NULL;
    503:   for (f = Nf; f < NfNew; ++f) tmpexactCtx_t[f] = NULL;
    504:   PetscFree4(prob->exactSol, prob->exactCtx, prob->exactSol_t, prob->exactCtx_t);
    505:   prob->exactSol = tmpexactSol;
    506:   prob->exactCtx = tmpexactCtx;
    507:   prob->exactSol_t = tmpexactSol_t;
    508:   prob->exactCtx_t = tmpexactCtx_t;
    509:   return 0;
    510: }

    512: /*@
    513:   PetscDSDestroy - Destroys a PetscDS object

    515:   Collective on prob

    517:   Input Parameter:
    518: . prob - the PetscDS object to destroy

    520:   Level: developer

    522: .seealso PetscDSView()
    523: @*/
    524: PetscErrorCode PetscDSDestroy(PetscDS *ds)
    525: {
    526:   PetscInt       f;

    528:   if (!*ds) return 0;

    531:   if (--((PetscObject)(*ds))->refct > 0) {*ds = NULL; return 0;}
    532:   ((PetscObject) (*ds))->refct = 0;
    533:   if ((*ds)->subprobs) {
    534:     PetscInt dim, d;

    536:     PetscDSGetSpatialDimension(*ds, &dim);
    537:     for (d = 0; d < dim; ++d) PetscDSDestroy(&(*ds)->subprobs[d]);
    538:   }
    539:   PetscFree((*ds)->subprobs);
    540:   PetscDSDestroyStructs_Static(*ds);
    541:   for (f = 0; f < (*ds)->Nf; ++f) {
    542:     PetscObjectDereference((*ds)->disc[f]);
    543:   }
    544:   PetscFree4((*ds)->disc, (*ds)->implicit, (*ds)->cohesive, (*ds)->jetDegree);
    545:   PetscWeakFormDestroy(&(*ds)->wf);
    546:   PetscFree2((*ds)->update,(*ds)->ctx);
    547:   PetscFree4((*ds)->exactSol,(*ds)->exactCtx,(*ds)->exactSol_t,(*ds)->exactCtx_t);
    548:   if ((*ds)->ops->destroy) (*(*ds)->ops->destroy)(*ds);
    549:   PetscDSDestroyBoundary(*ds);
    550:   PetscFree((*ds)->constants);
    551:   PetscHeaderDestroy(ds);
    552:   return 0;
    553: }

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

    558:   Collective

    560:   Input Parameter:
    561: . comm - The communicator for the PetscDS object

    563:   Output Parameter:
    564: . ds   - The PetscDS object

    566:   Level: beginner

    568: .seealso: PetscDSSetType(), PETSCDSBASIC
    569: @*/
    570: PetscErrorCode PetscDSCreate(MPI_Comm comm, PetscDS *ds)
    571: {
    572:   PetscDS        p;

    575:   *ds  = NULL;
    576:   PetscDSInitializePackage();

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

    580:   p->Nf           = 0;
    581:   p->setup        = PETSC_FALSE;
    582:   p->numConstants = 0;
    583:   p->constants    = NULL;
    584:   p->dimEmbed     = -1;
    585:   p->useJacPre    = PETSC_TRUE;
    586:   PetscWeakFormCreate(comm, &p->wf);

    588:   *ds = p;
    589:   return 0;
    590: }

    592: /*@
    593:   PetscDSGetNumFields - Returns the number of fields in the DS

    595:   Not collective

    597:   Input Parameter:
    598: . prob - The PetscDS object

    600:   Output Parameter:
    601: . Nf - The number of fields

    603:   Level: beginner

    605: .seealso: PetscDSGetSpatialDimension(), PetscDSCreate()
    606: @*/
    607: PetscErrorCode PetscDSGetNumFields(PetscDS prob, PetscInt *Nf)
    608: {
    611:   *Nf = prob->Nf;
    612:   return 0;
    613: }

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

    618:   Not collective

    620:   Input Parameter:
    621: . prob - The PetscDS object

    623:   Output Parameter:
    624: . dim - The spatial dimension

    626:   Level: beginner

    628: .seealso: PetscDSGetCoordinateDimension(), PetscDSGetNumFields(), PetscDSCreate()
    629: @*/
    630: PetscErrorCode PetscDSGetSpatialDimension(PetscDS prob, PetscInt *dim)
    631: {
    634:   *dim = 0;
    635:   if (prob->Nf) {
    636:     PetscObject  obj;
    637:     PetscClassId id;

    639:     PetscDSGetDiscretization(prob, 0, &obj);
    640:     if (obj) {
    641:       PetscObjectGetClassId(obj, &id);
    642:       if (id == PETSCFE_CLASSID)      PetscFEGetSpatialDimension((PetscFE) obj, dim);
    643:       else if (id == PETSCFV_CLASSID) PetscFVGetSpatialDimension((PetscFV) obj, dim);
    644:       else SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
    645:     }
    646:   }
    647:   return 0;
    648: }

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

    653:   Not collective

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

    658:   Output Parameter:
    659: . dimEmbed - The coordinate dimension

    661:   Level: beginner

    663: .seealso: PetscDSSetCoordinateDimension(), PetscDSGetSpatialDimension(), PetscDSGetNumFields(), PetscDSCreate()
    664: @*/
    665: PetscErrorCode PetscDSGetCoordinateDimension(PetscDS prob, PetscInt *dimEmbed)
    666: {
    670:   *dimEmbed = prob->dimEmbed;
    671:   return 0;
    672: }

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

    677:   Logically collective on prob

    679:   Input Parameters:
    680: + prob - The PetscDS object
    681: - dimEmbed - The coordinate dimension

    683:   Level: beginner

    685: .seealso: PetscDSGetCoordinateDimension(), PetscDSGetSpatialDimension(), PetscDSGetNumFields(), PetscDSCreate()
    686: @*/
    687: PetscErrorCode PetscDSSetCoordinateDimension(PetscDS prob, PetscInt dimEmbed)
    688: {
    691:   prob->dimEmbed = dimEmbed;
    692:   return 0;
    693: }

    695: /*@
    696:   PetscDSIsCohesive - Returns the flag indicating that this DS is for a cohesive cell

    698:   Not collective

    700:   Input Parameter:
    701: . ds - The PetscDS object

    703:   Output Parameter:
    704: . isCohesive - The flag

    706:   Level: developer

    708: .seealso: PetscDSGetNumCohesive(), PetscDSGetCohesive(), PetscDSSetCohesive(), PetscDSCreate()
    709: @*/
    710: PetscErrorCode PetscDSIsCohesive(PetscDS ds, PetscBool *isCohesive)
    711: {
    714:   *isCohesive = ds->isCohesive;
    715:   return 0;
    716: }

    718: /*@
    719:   PetscDSGetNumCohesive - Returns the numer of cohesive fields, meaning those defined on the interior of a cohesive cell

    721:   Not collective

    723:   Input Parameter:
    724: . ds - The PetscDS object

    726:   Output Parameter:
    727: . numCohesive - The number of cohesive fields

    729:   Level: developer

    731: .seealso: PetscDSSetCohesive(), PetscDSCreate()
    732: @*/
    733: PetscErrorCode PetscDSGetNumCohesive(PetscDS ds, PetscInt *numCohesive)
    734: {
    735:   PetscInt f;

    739:   *numCohesive = 0;
    740:   for (f = 0;  f < ds->Nf; ++f) *numCohesive += ds->cohesive[f] ? 1 : 0;
    741:   return 0;
    742: }

    744: /*@
    745:   PetscDSGetCohesive - Returns the flag indicating that a field is cohesive, meaning it is defined on the interior of a cohesive cell

    747:   Not collective

    749:   Input Parameters:
    750: + ds - The PetscDS object
    751: - f  - The field index

    753:   Output Parameter:
    754: . isCohesive - The flag

    756:   Level: developer

    758: .seealso: PetscDSSetCohesive(), PetscDSIsCohesive(), PetscDSCreate()
    759: @*/
    760: PetscErrorCode PetscDSGetCohesive(PetscDS ds, PetscInt f, PetscBool *isCohesive)
    761: {
    765:   *isCohesive = ds->cohesive[f];
    766:   return 0;
    767: }

    769: /*@
    770:   PetscDSSetCohesive - Set the flag indicating that a field is cohesive, meaning it is defined on the interior of a cohesive cell

    772:   Not collective

    774:   Input Parameters:
    775: + ds - The PetscDS object
    776: . f  - The field index
    777: - isCohesive - The flag for a cohesive field

    779:   Level: developer

    781: .seealso: PetscDSGetCohesive(), PetscDSIsCohesive(), PetscDSCreate()
    782: @*/
    783: PetscErrorCode PetscDSSetCohesive(PetscDS ds, PetscInt f, PetscBool isCohesive)
    784: {
    785:   PetscInt i;

    789:   ds->cohesive[f] = isCohesive;
    790:   ds->isCohesive = PETSC_FALSE;
    791:   for (i = 0; i < ds->Nf; ++i) ds->isCohesive = ds->isCohesive || ds->cohesive[f] ? PETSC_TRUE : PETSC_FALSE;
    792:   return 0;
    793: }

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

    798:   Not collective

    800:   Input Parameter:
    801: . prob - The PetscDS object

    803:   Output Parameter:
    804: . dim - The total problem dimension

    806:   Level: beginner

    808: .seealso: PetscDSGetNumFields(), PetscDSCreate()
    809: @*/
    810: PetscErrorCode PetscDSGetTotalDimension(PetscDS prob, PetscInt *dim)
    811: {
    813:   PetscDSSetUp(prob);
    815:   *dim = prob->totDim;
    816:   return 0;
    817: }

    819: /*@
    820:   PetscDSGetTotalComponents - Returns the total number of components in this system

    822:   Not collective

    824:   Input Parameter:
    825: . prob - The PetscDS object

    827:   Output Parameter:
    828: . dim - The total number of components

    830:   Level: beginner

    832: .seealso: PetscDSGetNumFields(), PetscDSCreate()
    833: @*/
    834: PetscErrorCode PetscDSGetTotalComponents(PetscDS prob, PetscInt *Nc)
    835: {
    837:   PetscDSSetUp(prob);
    839:   *Nc = prob->totComp;
    840:   return 0;
    841: }

    843: /*@
    844:   PetscDSGetDiscretization - Returns the discretization object for the given field

    846:   Not collective

    848:   Input Parameters:
    849: + prob - The PetscDS object
    850: - f - The field number

    852:   Output Parameter:
    853: . disc - The discretization object

    855:   Level: beginner

    857: .seealso: PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    858: @*/
    859: PetscErrorCode PetscDSGetDiscretization(PetscDS prob, PetscInt f, PetscObject *disc)
    860: {
    865:   *disc = prob->disc[f];
    866:   return 0;
    867: }

    869: /*@
    870:   PetscDSSetDiscretization - Sets the discretization object for the given field

    872:   Not collective

    874:   Input Parameters:
    875: + prob - The PetscDS object
    876: . f - The field number
    877: - disc - The discretization object

    879:   Level: beginner

    881: .seealso: PetscDSGetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    882: @*/
    883: PetscErrorCode PetscDSSetDiscretization(PetscDS prob, PetscInt f, PetscObject disc)
    884: {
    888:   PetscDSEnlarge_Static(prob, f+1);
    889:   PetscObjectDereference(prob->disc[f]);
    890:   prob->disc[f] = disc;
    891:   PetscObjectReference(disc);
    892:   if (disc) {
    893:     PetscClassId id;

    895:     PetscObjectGetClassId(disc, &id);
    896:     if (id == PETSCFE_CLASSID) {
    897:       PetscDSSetImplicit(prob, f, PETSC_TRUE);
    898:     } else if (id == PETSCFV_CLASSID) {
    899:       PetscDSSetImplicit(prob, f, PETSC_FALSE);
    900:     }
    901:     PetscDSSetJetDegree(prob, f, 1);
    902:   }
    903:   return 0;
    904: }

    906: /*@
    907:   PetscDSGetWeakForm - Returns the weak form object

    909:   Not collective

    911:   Input Parameter:
    912: . ds - The PetscDS object

    914:   Output Parameter:
    915: . wf - The weak form object

    917:   Level: beginner

    919: .seealso: PetscDSSetWeakForm(), PetscDSGetNumFields(), PetscDSCreate()
    920: @*/
    921: PetscErrorCode PetscDSGetWeakForm(PetscDS ds, PetscWeakForm *wf)
    922: {
    925:   *wf = ds->wf;
    926:   return 0;
    927: }

    929: /*@
    930:   PetscDSSetWeakForm - Sets the weak form object

    932:   Not collective

    934:   Input Parameters:
    935: + ds - The PetscDS object
    936: - wf - The weak form object

    938:   Level: beginner

    940: .seealso: PetscDSGetWeakForm(), PetscDSGetNumFields(), PetscDSCreate()
    941: @*/
    942: PetscErrorCode PetscDSSetWeakForm(PetscDS ds, PetscWeakForm wf)
    943: {
    946:   PetscObjectDereference((PetscObject) ds->wf);
    947:   ds->wf = wf;
    948:   PetscObjectReference((PetscObject) wf);
    949:   PetscWeakFormSetNumFields(wf, ds->Nf);
    950:   return 0;
    951: }

    953: /*@
    954:   PetscDSAddDiscretization - Adds a discretization object

    956:   Not collective

    958:   Input Parameters:
    959: + prob - The PetscDS object
    960: - disc - The boundary discretization object

    962:   Level: beginner

    964: .seealso: PetscDSGetDiscretization(), PetscDSSetDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    965: @*/
    966: PetscErrorCode PetscDSAddDiscretization(PetscDS prob, PetscObject disc)
    967: {
    968:   PetscDSSetDiscretization(prob, prob->Nf, disc);
    969:   return 0;
    970: }

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

    975:   Not collective

    977:   Input Parameter:
    978: . prob - The PetscDS object

    980:   Output Parameter:
    981: . q - The quadrature object

    983: Level: intermediate

    985: .seealso: PetscDSSetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    986: @*/
    987: PetscErrorCode PetscDSGetQuadrature(PetscDS prob, PetscQuadrature *q)
    988: {
    989:   PetscObject    obj;
    990:   PetscClassId   id;

    992:   *q = NULL;
    993:   if (!prob->Nf) return 0;
    994:   PetscDSGetDiscretization(prob, 0, &obj);
    995:   PetscObjectGetClassId(obj, &id);
    996:   if      (id == PETSCFE_CLASSID) PetscFEGetQuadrature((PetscFE) obj, q);
    997:   else if (id == PETSCFV_CLASSID) PetscFVGetQuadrature((PetscFV) obj, q);
    998:   else SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
    999:   return 0;
    1000: }

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

    1005:   Not collective

    1007:   Input Parameters:
    1008: + prob - The PetscDS object
    1009: - f - The field number

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

    1014:   Level: developer

    1016: .seealso: PetscDSSetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    1017: @*/
    1018: PetscErrorCode PetscDSGetImplicit(PetscDS prob, PetscInt f, PetscBool *implicit)
    1019: {
    1023:   *implicit = prob->implicit[f];
    1024:   return 0;
    1025: }

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

    1030:   Not collective

    1032:   Input Parameters:
    1033: + prob - The PetscDS object
    1034: . f - The field number
    1035: - implicit - The flag indicating what kind of solve to use for this field

    1037:   Level: developer

    1039: .seealso: PetscDSGetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    1040: @*/
    1041: PetscErrorCode PetscDSSetImplicit(PetscDS prob, PetscInt f, PetscBool implicit)
    1042: {
    1045:   prob->implicit[f] = implicit;
    1046:   return 0;
    1047: }

    1049: /*@
    1050:   PetscDSGetJetDegree - Returns the highest derivative for this field equation, or the k-jet that the discretization needs to tabulate.

    1052:   Not collective

    1054:   Input Parameters:
    1055: + ds - The PetscDS object
    1056: - f  - The field number

    1058:   Output Parameter:
    1059: . k  - The highest derivative we need to tabulate

    1061:   Level: developer

    1063: .seealso: PetscDSSetJetDegree(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    1064: @*/
    1065: PetscErrorCode PetscDSGetJetDegree(PetscDS ds, PetscInt f, PetscInt *k)
    1066: {
    1070:   *k = ds->jetDegree[f];
    1071:   return 0;
    1072: }

    1074: /*@
    1075:   PetscDSSetJetDegree - Set the highest derivative for this field equation, or the k-jet that the discretization needs to tabulate.

    1077:   Not collective

    1079:   Input Parameters:
    1080: + ds - The PetscDS object
    1081: . f  - The field number
    1082: - k  - The highest derivative we need to tabulate

    1084:   Level: developer

    1086: .seealso: PetscDSGetJetDegree(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    1087: @*/
    1088: PetscErrorCode PetscDSSetJetDegree(PetscDS ds, PetscInt f, PetscInt k)
    1089: {
    1092:   ds->jetDegree[f] = k;
    1093:   return 0;
    1094: }

    1096: PetscErrorCode PetscDSGetObjective(PetscDS ds, PetscInt f,
    1097:                                    void (**obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1098:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1099:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1100:                                                 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]))
    1101: {
    1102:   PetscPointFunc *tmp;
    1103:   PetscInt        n;

    1108:   PetscWeakFormGetObjective(ds->wf, NULL, 0, f, 0, &n, &tmp);
    1109:   *obj = tmp ? tmp[0] : NULL;
    1110:   return 0;
    1111: }

    1113: PetscErrorCode PetscDSSetObjective(PetscDS ds, PetscInt f,
    1114:                                    void (*obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1115:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1116:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1117:                                                PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]))
    1118: {
    1122:   PetscWeakFormSetIndexObjective(ds->wf, NULL, 0, f, 0, 0, obj);
    1123:   return 0;
    1124: }

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

    1129:   Not collective

    1131:   Input Parameters:
    1132: + ds - The PetscDS
    1133: - f  - The test field number

    1135:   Output Parameters:
    1136: + f0 - integrand for the test function term
    1137: - f1 - integrand for the test function gradient term

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

    1141:   \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)

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

    1145: $ f0(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[], PetscScalar f0[])

    1150: + dim - the spatial dimension
    1151: . Nf - the number of fields
    1152: . uOff - the offset into u[] and u_t[] for each field
    1153: . uOff_x - the offset into u_x[] for each field
    1154: . u - each field evaluated at the current point
    1155: . u_t - the time derivative of each field evaluated at the current point
    1156: . u_x - the gradient of each field evaluated at the current point
    1157: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1158: . aOff_x - the offset into a_x[] for each auxiliary field
    1159: . a - each auxiliary field evaluated at the current point
    1160: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1161: . a_x - the gradient of auxiliary each field evaluated at the current point
    1162: . t - current time
    1163: . x - coordinates of the current point
    1164: . numConstants - number of constant parameters
    1165: . constants - constant parameters
    1166: - f0 - output values at the current point

    1168:   Level: intermediate

    1170: .seealso: PetscDSSetResidual()
    1171: @*/
    1172: PetscErrorCode PetscDSGetResidual(PetscDS ds, PetscInt f,
    1173:                                   void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1174:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1175:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1176:                                               PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
    1177:                                   void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1178:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1179:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1180:                                               PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
    1181: {
    1182:   PetscPointFunc *tmp0, *tmp1;
    1183:   PetscInt        n0, n1;

    1187:   PetscWeakFormGetResidual(ds->wf, NULL, 0, f, 0, &n0, &tmp0, &n1, &tmp1);
    1188:   *f0  = tmp0 ? tmp0[0] : NULL;
    1189:   *f1  = tmp1 ? tmp1[0] : NULL;
    1190:   return 0;
    1191: }

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

    1196:   Not collective

    1198:   Input Parameters:
    1199: + ds - The PetscDS
    1200: . f  - The test field number
    1201: . f0 - integrand for the test function term
    1202: - f1 - integrand for the test function gradient term

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

    1206:   \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)

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

    1210: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1211: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1212: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1213: $    PetscReal t, const PetscReal x[], PetscScalar f0[])

    1215: + dim - the spatial dimension
    1216: . Nf - the number of fields
    1217: . uOff - the offset into u[] and u_t[] for each field
    1218: . uOff_x - the offset into u_x[] for each field
    1219: . u - each field evaluated at the current point
    1220: . u_t - the time derivative of each field evaluated at the current point
    1221: . u_x - the gradient of each field evaluated at the current point
    1222: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1223: . aOff_x - the offset into a_x[] for each auxiliary field
    1224: . a - each auxiliary field evaluated at the current point
    1225: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1226: . a_x - the gradient of auxiliary each field evaluated at the current point
    1227: . t - current time
    1228: . x - coordinates of the current point
    1229: . numConstants - number of constant parameters
    1230: . constants - constant parameters
    1231: - f0 - output values at the current point

    1233:   Level: intermediate

    1235: .seealso: PetscDSGetResidual()
    1236: @*/
    1237: PetscErrorCode PetscDSSetResidual(PetscDS ds, PetscInt f,
    1238:                                   void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1239:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1240:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1241:                                              PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
    1242:                                   void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1243:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1244:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1245:                                              PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
    1246: {
    1251:   PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1);
    1252:   return 0;
    1253: }

    1255: /*@C
    1256:   PetscDSGetRHSResidual - Get the pointwise RHS residual function for explicit timestepping for a given test field

    1258:   Not collective

    1260:   Input Parameters:
    1261: + ds - The PetscDS
    1262: - f  - The test field number

    1264:   Output Parameters:
    1265: + f0 - integrand for the test function term
    1266: - f1 - integrand for the test function gradient term

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

    1270:   \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)

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

    1274: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1275: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1276: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1277: $    PetscReal t, const PetscReal x[], PetscScalar f0[])

    1279: + dim - the spatial dimension
    1280: . Nf - the number of fields
    1281: . uOff - the offset into u[] and u_t[] for each field
    1282: . uOff_x - the offset into u_x[] for each field
    1283: . u - each field evaluated at the current point
    1284: . u_t - the time derivative of each field evaluated at the current point
    1285: . u_x - the gradient of each field evaluated at the current point
    1286: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1287: . aOff_x - the offset into a_x[] for each auxiliary field
    1288: . a - each auxiliary field evaluated at the current point
    1289: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1290: . a_x - the gradient of auxiliary each field evaluated at the current point
    1291: . t - current time
    1292: . x - coordinates of the current point
    1293: . numConstants - number of constant parameters
    1294: . constants - constant parameters
    1295: - f0 - output values at the current point

    1297:   Level: intermediate

    1299: .seealso: PetscDSSetRHSResidual()
    1300: @*/
    1301: PetscErrorCode PetscDSGetRHSResidual(PetscDS ds, PetscInt f,
    1302:                                      void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1303:                                                  const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1304:                                                  const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1305:                                                  PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
    1306:                                      void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1307:                                                  const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1308:                                                  const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1309:                                                  PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
    1310: {
    1311:   PetscPointFunc *tmp0, *tmp1;
    1312:   PetscInt        n0, n1;

    1316:   PetscWeakFormGetResidual(ds->wf, NULL, 0, f, 100, &n0, &tmp0, &n1, &tmp1);
    1317:   *f0  = tmp0 ? tmp0[0] : NULL;
    1318:   *f1  = tmp1 ? tmp1[0] : NULL;
    1319:   return 0;
    1320: }

    1322: /*@C
    1323:   PetscDSSetRHSResidual - Set the pointwise residual function for explicit timestepping for a given test field

    1325:   Not collective

    1327:   Input Parameters:
    1328: + ds - The PetscDS
    1329: . f  - The test field number
    1330: . f0 - integrand for the test function term
    1331: - f1 - integrand for the test function gradient term

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

    1335:   \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)

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

    1339: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1340: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1341: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1342: $    PetscReal t, const PetscReal x[], PetscScalar f0[])

    1344: + dim - the spatial dimension
    1345: . Nf - the number of fields
    1346: . uOff - the offset into u[] and u_t[] for each field
    1347: . uOff_x - the offset into u_x[] for each field
    1348: . u - each field evaluated at the current point
    1349: . u_t - the time derivative of each field evaluated at the current point
    1350: . u_x - the gradient of each field evaluated at the current point
    1351: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1352: . aOff_x - the offset into a_x[] for each auxiliary field
    1353: . a - each auxiliary field evaluated at the current point
    1354: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1355: . a_x - the gradient of auxiliary each field evaluated at the current point
    1356: . t - current time
    1357: . x - coordinates of the current point
    1358: . numConstants - number of constant parameters
    1359: . constants - constant parameters
    1360: - f0 - output values at the current point

    1362:   Level: intermediate

    1364: .seealso: PetscDSGetResidual()
    1365: @*/
    1366: PetscErrorCode PetscDSSetRHSResidual(PetscDS ds, PetscInt f,
    1367:                                      void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1368:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1369:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1370:                                                 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
    1371:                                      void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1372:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1373:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1374:                                                 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
    1375: {
    1380:   PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 100, 0, f0, 0, f1);
    1381:   return 0;
    1382: }

    1384: /*@C
    1385:   PetscDSHasJacobian - Signals that Jacobian functions have been set

    1387:   Not collective

    1389:   Input Parameter:
    1390: . prob - The PetscDS

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

    1395:   Level: intermediate

    1397: .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
    1398: @*/
    1399: PetscErrorCode PetscDSHasJacobian(PetscDS ds, PetscBool *hasJac)
    1400: {
    1402:   PetscWeakFormHasJacobian(ds->wf, hasJac);
    1403:   return 0;
    1404: }

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

    1409:   Not collective

    1411:   Input Parameters:
    1412: + ds - The PetscDS
    1413: . f  - The test field number
    1414: - g  - The field number

    1416:   Output Parameters:
    1417: + g0 - integrand for the test and basis function term
    1418: . g1 - integrand for the test function and basis function gradient term
    1419: . g2 - integrand for the test function gradient and basis function term
    1420: - g3 - integrand for the test function gradient and basis function gradient term

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

    1424:   \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

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

    1428: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1429: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1430: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1431: $    PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])

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

    1452:   Level: intermediate

    1454: .seealso: PetscDSSetJacobian()
    1455: @*/
    1456: PetscErrorCode PetscDSGetJacobian(PetscDS ds, PetscInt f, PetscInt g,
    1457:                                   void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1458:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1459:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1460:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    1461:                                   void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1462:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1463:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1464:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    1465:                                   void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1466:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1467:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1468:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    1469:                                   void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1470:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1471:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1472:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    1473: {
    1474:   PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
    1475:   PetscInt       n0, n1, n2, n3;

    1480:   PetscWeakFormGetJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);
    1481:   *g0  = tmp0 ? tmp0[0] : NULL;
    1482:   *g1  = tmp1 ? tmp1[0] : NULL;
    1483:   *g2  = tmp2 ? tmp2[0] : NULL;
    1484:   *g3  = tmp3 ? tmp3[0] : NULL;
    1485:   return 0;
    1486: }

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

    1491:   Not collective

    1493:   Input Parameters:
    1494: + ds - The PetscDS
    1495: . f  - The test field number
    1496: . g  - The field number
    1497: . g0 - integrand for the test and basis function term
    1498: . g1 - integrand for the test function and basis function gradient term
    1499: . g2 - integrand for the test function gradient and basis function term
    1500: - g3 - integrand for the test function gradient and basis function gradient term

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

    1504:   \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

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

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

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

    1532:   Level: intermediate

    1534: .seealso: PetscDSGetJacobian()
    1535: @*/
    1536: PetscErrorCode PetscDSSetJacobian(PetscDS ds, PetscInt f, PetscInt g,
    1537:                                   void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1538:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1539:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1540:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    1541:                                   void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1542:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1543:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1544:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    1545:                                   void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1546:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1547:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1548:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    1549:                                   void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1550:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1551:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1552:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    1553: {
    1561:   PetscWeakFormSetIndexJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);
    1562:   return 0;
    1563: }

    1565: /*@C
    1566:   PetscDSUseJacobianPreconditioner - Whether to construct a Jacobian preconditioner

    1568:   Not collective

    1570:   Input Parameters:
    1571: + prob - The PetscDS
    1572: - useJacPre - flag that enables construction of a Jacobian preconditioner

    1574:   Level: intermediate

    1576: .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
    1577: @*/
    1578: PetscErrorCode PetscDSUseJacobianPreconditioner(PetscDS prob, PetscBool useJacPre)
    1579: {
    1581:   prob->useJacPre = useJacPre;
    1582:   return 0;
    1583: }

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

    1588:   Not collective

    1590:   Input Parameter:
    1591: . prob - The PetscDS

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

    1596:   Level: intermediate

    1598: .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
    1599: @*/
    1600: PetscErrorCode PetscDSHasJacobianPreconditioner(PetscDS ds, PetscBool *hasJacPre)
    1601: {
    1603:   *hasJacPre = PETSC_FALSE;
    1604:   if (!ds->useJacPre) return 0;
    1605:   PetscWeakFormHasJacobianPreconditioner(ds->wf, hasJacPre);
    1606:   return 0;
    1607: }

    1609: /*@C
    1610:   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.

    1612:   Not collective

    1614:   Input Parameters:
    1615: + ds - The PetscDS
    1616: . f  - The test field number
    1617: - g  - The field number

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

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

    1627:   \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

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

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

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

    1655:   Level: intermediate

    1657: .seealso: PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
    1658: @*/
    1659: PetscErrorCode PetscDSGetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g,
    1660:                                   void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1661:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1662:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1663:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    1664:                                   void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1665:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1666:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1667:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    1668:                                   void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1669:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1670:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1671:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    1672:                                   void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1673:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1674:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1675:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    1676: {
    1677:   PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
    1678:   PetscInt       n0, n1, n2, n3;

    1683:   PetscWeakFormGetJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);
    1684:   *g0  = tmp0 ? tmp0[0] : NULL;
    1685:   *g1  = tmp1 ? tmp1[0] : NULL;
    1686:   *g2  = tmp2 ? tmp2[0] : NULL;
    1687:   *g3  = tmp3 ? tmp3[0] : NULL;
    1688:   return 0;
    1689: }

    1691: /*@C
    1692:   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.

    1694:   Not collective

    1696:   Input Parameters:
    1697: + ds - The PetscDS
    1698: . f  - The test field number
    1699: . g  - The field number
    1700: . g0 - integrand for the test and basis function term
    1701: . g1 - integrand for the test function and basis function gradient term
    1702: . g2 - integrand for the test function gradient and basis function term
    1703: - g3 - integrand for the test function gradient and basis function gradient term

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

    1707:   \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

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

    1711: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1712: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1713: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1714: $    PetscReal t, const PetscReal x[], PetscScalar g0[])

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

    1735:   Level: intermediate

    1737: .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobian()
    1738: @*/
    1739: PetscErrorCode PetscDSSetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g,
    1740:                                   void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1741:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1742:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1743:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    1744:                                   void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1745:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1746:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1747:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    1748:                                   void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1749:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1750:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1751:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    1752:                                   void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1753:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1754:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1755:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    1756: {
    1764:   PetscWeakFormSetIndexJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);
    1765:   return 0;
    1766: }

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

    1771:   Not collective

    1773:   Input Parameter:
    1774: . ds - The PetscDS

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

    1779:   Level: intermediate

    1781: .seealso: PetscDSGetDynamicJacobian(), PetscDSSetDynamicJacobian(), PetscDSGetJacobian()
    1782: @*/
    1783: PetscErrorCode PetscDSHasDynamicJacobian(PetscDS ds, PetscBool *hasDynJac)
    1784: {
    1786:   PetscWeakFormHasDynamicJacobian(ds->wf, hasDynJac);
    1787:   return 0;
    1788: }

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

    1793:   Not collective

    1795:   Input Parameters:
    1796: + ds - The PetscDS
    1797: . f  - The test field number
    1798: - g  - The field number

    1800:   Output Parameters:
    1801: + g0 - integrand for the test and basis function term
    1802: . g1 - integrand for the test function and basis function gradient term
    1803: . g2 - integrand for the test function gradient and basis function term
    1804: - g3 - integrand for the test function gradient and basis function gradient term

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

    1808:   \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

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

    1812: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1813: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1814: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1815: $    PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])

    1817: + dim - the spatial dimension
    1818: . Nf - the number of fields
    1819: . uOff - the offset into u[] and u_t[] for each field
    1820: . uOff_x - the offset into u_x[] for each field
    1821: . u - each field evaluated at the current point
    1822: . u_t - the time derivative of each field evaluated at the current point
    1823: . u_x - the gradient of each field evaluated at the current point
    1824: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1825: . aOff_x - the offset into a_x[] for each auxiliary field
    1826: . a - each auxiliary field evaluated at the current point
    1827: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1828: . a_x - the gradient of auxiliary each field evaluated at the current point
    1829: . t - current time
    1830: . u_tShift - the multiplier a for dF/dU_t
    1831: . x - coordinates of the current point
    1832: . numConstants - number of constant parameters
    1833: . constants - constant parameters
    1834: - g0 - output values at the current point

    1836:   Level: intermediate

    1838: .seealso: PetscDSSetJacobian()
    1839: @*/
    1840: PetscErrorCode PetscDSGetDynamicJacobian(PetscDS ds, PetscInt f, PetscInt g,
    1841:                                          void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1842:                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1843:                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1844:                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    1845:                                          void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1846:                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1847:                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1848:                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    1849:                                          void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1850:                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1851:                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1852:                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    1853:                                          void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1854:                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1855:                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1856:                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    1857: {
    1858:   PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
    1859:   PetscInt       n0, n1, n2, n3;

    1864:   PetscWeakFormGetDynamicJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);
    1865:   *g0  = tmp0 ? tmp0[0] : NULL;
    1866:   *g1  = tmp1 ? tmp1[0] : NULL;
    1867:   *g2  = tmp2 ? tmp2[0] : NULL;
    1868:   *g3  = tmp3 ? tmp3[0] : NULL;
    1869:   return 0;
    1870: }

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

    1875:   Not collective

    1877:   Input Parameters:
    1878: + ds - The PetscDS
    1879: . f  - The test field number
    1880: . g  - The field number
    1881: . g0 - integrand for the test and basis function term
    1882: . g1 - integrand for the test function and basis function gradient term
    1883: . g2 - integrand for the test function gradient and basis function term
    1884: - g3 - integrand for the test function gradient and basis function gradient term

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

    1888:   \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

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

    1892: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1893: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1894: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1895: $    PetscReal t, const PetscReal x[], PetscScalar g0[])

    1897: + dim - the spatial dimension
    1898: . Nf - the number of fields
    1899: . uOff - the offset into u[] and u_t[] for each field
    1900: . uOff_x - the offset into u_x[] for each field
    1901: . u - each field evaluated at the current point
    1902: . u_t - the time derivative of each field evaluated at the current point
    1903: . u_x - the gradient of each field evaluated at the current point
    1904: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1905: . aOff_x - the offset into a_x[] for each auxiliary field
    1906: . a - each auxiliary field evaluated at the current point
    1907: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1908: . a_x - the gradient of auxiliary each field evaluated at the current point
    1909: . t - current time
    1910: . u_tShift - the multiplier a for dF/dU_t
    1911: . x - coordinates of the current point
    1912: . numConstants - number of constant parameters
    1913: . constants - constant parameters
    1914: - g0 - output values at the current point

    1916:   Level: intermediate

    1918: .seealso: PetscDSGetJacobian()
    1919: @*/
    1920: PetscErrorCode PetscDSSetDynamicJacobian(PetscDS ds, PetscInt f, PetscInt g,
    1921:                                          void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1922:                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1923:                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1924:                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    1925:                                          void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1926:                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1927:                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1928:                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    1929:                                          void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1930:                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1931:                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1932:                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    1933:                                          void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1934:                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1935:                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1936:                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    1937: {
    1945:   PetscWeakFormSetIndexDynamicJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);
    1946:   return 0;
    1947: }

    1949: /*@C
    1950:   PetscDSGetRiemannSolver - Returns the Riemann solver for the given field

    1952:   Not collective

    1954:   Input Parameters:
    1955: + ds - The PetscDS object
    1956: - f  - The field number

    1958:   Output Parameter:
    1959: . r    - Riemann solver

    1961:   Calling sequence for r:

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

    1965: + dim  - The spatial dimension
    1966: . Nf   - The number of fields
    1967: . x    - The coordinates at a point on the interface
    1968: . n    - The normal vector to the interface
    1969: . uL   - The state vector to the left of the interface
    1970: . uR   - The state vector to the right of the interface
    1971: . flux - output array of flux through the interface
    1972: . numConstants - number of constant parameters
    1973: . constants - constant parameters
    1974: - ctx  - optional user context

    1976:   Level: intermediate

    1978: .seealso: PetscDSSetRiemannSolver()
    1979: @*/
    1980: PetscErrorCode PetscDSGetRiemannSolver(PetscDS ds, PetscInt f,
    1981:                                        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))
    1982: {
    1983:   PetscRiemannFunc *tmp;
    1984:   PetscInt          n;

    1989:   PetscWeakFormGetRiemannSolver(ds->wf, NULL, 0, f, 0, &n, &tmp);
    1990:   *r   = tmp ? tmp[0] : NULL;
    1991:   return 0;
    1992: }

    1994: /*@C
    1995:   PetscDSSetRiemannSolver - Sets the Riemann solver for the given field

    1997:   Not collective

    1999:   Input Parameters:
    2000: + ds - The PetscDS object
    2001: . f  - The field number
    2002: - r  - Riemann solver

    2004:   Calling sequence for r:

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

    2008: + dim  - The spatial dimension
    2009: . Nf   - The number of fields
    2010: . x    - The coordinates at a point on the interface
    2011: . n    - The normal vector to the interface
    2012: . uL   - The state vector to the left of the interface
    2013: . uR   - The state vector to the right of the interface
    2014: . flux - output array of flux through the interface
    2015: . numConstants - number of constant parameters
    2016: . constants - constant parameters
    2017: - ctx  - optional user context

    2019:   Level: intermediate

    2021: .seealso: PetscDSGetRiemannSolver()
    2022: @*/
    2023: PetscErrorCode PetscDSSetRiemannSolver(PetscDS ds, PetscInt f,
    2024:                                        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))
    2025: {
    2029:   PetscWeakFormSetIndexRiemannSolver(ds->wf, NULL, 0, f, 0, 0, r);
    2030:   return 0;
    2031: }

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

    2036:   Not collective

    2038:   Input Parameters:
    2039: + ds - The PetscDS
    2040: - f  - The field number

    2042:   Output Parameter:
    2043: . update - update function

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

    2047: $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2048: $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2049: $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2050: $        PetscReal t, const PetscReal x[], PetscScalar uNew[])

    2052: + dim - the spatial dimension
    2053: . Nf - the number of fields
    2054: . uOff - the offset into u[] and u_t[] for each field
    2055: . uOff_x - the offset into u_x[] for each field
    2056: . u - each field evaluated at the current point
    2057: . u_t - the time derivative of each field evaluated at the current point
    2058: . u_x - the gradient of each field evaluated at the current point
    2059: . aOff - the offset into a[] and a_t[] for each auxiliary field
    2060: . aOff_x - the offset into a_x[] for each auxiliary field
    2061: . a - each auxiliary field evaluated at the current point
    2062: . a_t - the time derivative of each auxiliary field evaluated at the current point
    2063: . a_x - the gradient of auxiliary each field evaluated at the current point
    2064: . t - current time
    2065: . x - coordinates of the current point
    2066: - uNew - new value for field at the current point

    2068:   Level: intermediate

    2070: .seealso: PetscDSSetUpdate(), PetscDSSetResidual()
    2071: @*/
    2072: PetscErrorCode PetscDSGetUpdate(PetscDS ds, PetscInt f,
    2073:                                   void (**update)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2074:                                                   const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2075:                                                   const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2076:                                                   PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[]))
    2077: {
    2081:   return 0;
    2082: }

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

    2087:   Not collective

    2089:   Input Parameters:
    2090: + ds     - The PetscDS
    2091: . f      - The field number
    2092: - update - update function

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

    2096: $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2097: $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2098: $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2099: $        PetscReal t, const PetscReal x[], PetscScalar uNew[])

    2101: + dim - the spatial dimension
    2102: . Nf - the number of fields
    2103: . uOff - the offset into u[] and u_t[] for each field
    2104: . uOff_x - the offset into u_x[] for each field
    2105: . u - each field evaluated at the current point
    2106: . u_t - the time derivative of each field evaluated at the current point
    2107: . u_x - the gradient of each field evaluated at the current point
    2108: . aOff - the offset into a[] and a_t[] for each auxiliary field
    2109: . aOff_x - the offset into a_x[] for each auxiliary field
    2110: . a - each auxiliary field evaluated at the current point
    2111: . a_t - the time derivative of each auxiliary field evaluated at the current point
    2112: . a_x - the gradient of auxiliary each field evaluated at the current point
    2113: . t - current time
    2114: . x - coordinates of the current point
    2115: - uNew - new field values at the current point

    2117:   Level: intermediate

    2119: .seealso: PetscDSGetResidual()
    2120: @*/
    2121: PetscErrorCode PetscDSSetUpdate(PetscDS ds, PetscInt f,
    2122:                                 void (*update)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2123:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2124:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2125:                                                PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[]))
    2126: {
    2130:   PetscDSEnlarge_Static(ds, f+1);
    2131:   ds->update[f] = update;
    2132:   return 0;
    2133: }

    2135: PetscErrorCode PetscDSGetContext(PetscDS ds, PetscInt f, void *ctx)
    2136: {
    2140:   *(void**)ctx = ds->ctx[f];
    2141:   return 0;
    2142: }

    2144: PetscErrorCode PetscDSSetContext(PetscDS ds, PetscInt f, void *ctx)
    2145: {
    2148:   PetscDSEnlarge_Static(ds, f+1);
    2149:   ds->ctx[f] = ctx;
    2150:   return 0;
    2151: }

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

    2156:   Not collective

    2158:   Input Parameters:
    2159: + ds - The PetscDS
    2160: - f  - The test field number

    2162:   Output Parameters:
    2163: + f0 - boundary integrand for the test function term
    2164: - f1 - boundary integrand for the test function gradient term

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

    2168:   \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

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

    2172: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2173: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2174: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2175: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])

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

    2196:   Level: intermediate

    2198: .seealso: PetscDSSetBdResidual()
    2199: @*/
    2200: PetscErrorCode PetscDSGetBdResidual(PetscDS ds, PetscInt f,
    2201:                                     void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2202:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2203:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2204:                                                 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
    2205:                                     void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2206:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2207:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2208:                                                 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
    2209: {
    2210:   PetscBdPointFunc *tmp0, *tmp1;
    2211:   PetscInt          n0, n1;

    2215:   PetscWeakFormGetBdResidual(ds->wf, NULL, 0, f, 0, &n0, &tmp0, &n1, &tmp1);
    2216:   *f0  = tmp0 ? tmp0[0] : NULL;
    2217:   *f1  = tmp1 ? tmp1[0] : NULL;
    2218:   return 0;
    2219: }

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

    2224:   Not collective

    2226:   Input Parameters:
    2227: + ds - The PetscDS
    2228: . f  - The test field number
    2229: . f0 - boundary integrand for the test function term
    2230: - f1 - boundary integrand for the test function gradient term

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

    2234:   \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

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

    2238: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2239: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2240: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2241: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])

    2243: + dim - the spatial dimension
    2244: . Nf - the number of fields
    2245: . uOff - the offset into u[] and u_t[] for each field
    2246: . uOff_x - the offset into u_x[] for each field
    2247: . u - each field evaluated at the current point
    2248: . u_t - the time derivative of each field evaluated at the current point
    2249: . u_x - the gradient of each field evaluated at the current point
    2250: . aOff - the offset into a[] and a_t[] for each auxiliary field
    2251: . aOff_x - the offset into a_x[] for each auxiliary field
    2252: . a - each auxiliary field evaluated at the current point
    2253: . a_t - the time derivative of each auxiliary field evaluated at the current point
    2254: . a_x - the gradient of auxiliary each field evaluated at the current point
    2255: . t - current time
    2256: . x - coordinates of the current point
    2257: . n - unit normal at the current point
    2258: . numConstants - number of constant parameters
    2259: . constants - constant parameters
    2260: - f0 - output values at the current point

    2262:   Level: intermediate

    2264: .seealso: PetscDSGetBdResidual()
    2265: @*/
    2266: PetscErrorCode PetscDSSetBdResidual(PetscDS ds, PetscInt f,
    2267:                                     void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2268:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2269:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2270:                                                PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
    2271:                                     void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2272:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2273:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2274:                                                PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
    2275: {
    2278:   PetscWeakFormSetIndexBdResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1);
    2279:   return 0;
    2280: }

    2282: /*@
    2283:   PetscDSHasBdJacobian - Signals that boundary Jacobian functions have been set

    2285:   Not collective

    2287:   Input Parameter:
    2288: . ds - The PetscDS

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

    2293:   Level: intermediate

    2295: .seealso: PetscDSHasJacobian(), PetscDSSetBdJacobian(), PetscDSGetBdJacobian()
    2296: @*/
    2297: PetscErrorCode PetscDSHasBdJacobian(PetscDS ds, PetscBool *hasBdJac)
    2298: {
    2301:   PetscWeakFormHasBdJacobian(ds->wf, hasBdJac);
    2302:   return 0;
    2303: }

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

    2308:   Not collective

    2310:   Input Parameters:
    2311: + ds - The PetscDS
    2312: . f  - The test field number
    2313: - g  - The field number

    2315:   Output Parameters:
    2316: + g0 - integrand for the test and basis function term
    2317: . g1 - integrand for the test function and basis function gradient term
    2318: . g2 - integrand for the test function gradient and basis function term
    2319: - g3 - integrand for the test function gradient and basis function gradient term

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

    2323:   \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

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

    2327: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2328: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2329: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2330: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[])

    2332: + dim - the spatial dimension
    2333: . Nf - the number of fields
    2334: . uOff - the offset into u[] and u_t[] for each field
    2335: . uOff_x - the offset into u_x[] for each field
    2336: . u - each field evaluated at the current point
    2337: . u_t - the time derivative of each field evaluated at the current point
    2338: . u_x - the gradient of each field evaluated at the current point
    2339: . aOff - the offset into a[] and a_t[] for each auxiliary field
    2340: . aOff_x - the offset into a_x[] for each auxiliary field
    2341: . a - each auxiliary field evaluated at the current point
    2342: . a_t - the time derivative of each auxiliary field evaluated at the current point
    2343: . a_x - the gradient of auxiliary each field evaluated at the current point
    2344: . t - current time
    2345: . u_tShift - the multiplier a for dF/dU_t
    2346: . x - coordinates of the current point
    2347: . n - normal at the current point
    2348: . numConstants - number of constant parameters
    2349: . constants - constant parameters
    2350: - g0 - output values at the current point

    2352:   Level: intermediate

    2354: .seealso: PetscDSSetBdJacobian()
    2355: @*/
    2356: PetscErrorCode PetscDSGetBdJacobian(PetscDS ds, PetscInt f, PetscInt g,
    2357:                                     void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2358:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2359:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2360:                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    2361:                                     void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2362:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2363:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2364:                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    2365:                                     void (**g2)(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, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    2369:                                     void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2370:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2371:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2372:                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    2373: {
    2374:   PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3;
    2375:   PetscInt         n0, n1, n2, n3;

    2380:   PetscWeakFormGetBdJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);
    2381:   *g0  = tmp0 ? tmp0[0] : NULL;
    2382:   *g1  = tmp1 ? tmp1[0] : NULL;
    2383:   *g2  = tmp2 ? tmp2[0] : NULL;
    2384:   *g3  = tmp3 ? tmp3[0] : NULL;
    2385:   return 0;
    2386: }

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

    2391:   Not collective

    2393:   Input Parameters:
    2394: + ds - The PetscDS
    2395: . f  - The test field number
    2396: . g  - The field number
    2397: . g0 - integrand for the test and basis function term
    2398: . g1 - integrand for the test function and basis function gradient term
    2399: . g2 - integrand for the test function gradient and basis function term
    2400: - g3 - integrand for the test function gradient and basis function gradient term

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

    2404:   \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

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

    2408: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2409: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2410: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2411: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[])

    2413: + dim - the spatial dimension
    2414: . Nf - the number of fields
    2415: . uOff - the offset into u[] and u_t[] for each field
    2416: . uOff_x - the offset into u_x[] for each field
    2417: . u - each field evaluated at the current point
    2418: . u_t - the time derivative of each field evaluated at the current point
    2419: . u_x - the gradient of each field evaluated at the current point
    2420: . aOff - the offset into a[] and a_t[] for each auxiliary field
    2421: . aOff_x - the offset into a_x[] for each auxiliary field
    2422: . a - each auxiliary field evaluated at the current point
    2423: . a_t - the time derivative of each auxiliary field evaluated at the current point
    2424: . a_x - the gradient of auxiliary each field evaluated at the current point
    2425: . t - current time
    2426: . u_tShift - the multiplier a for dF/dU_t
    2427: . x - coordinates of the current point
    2428: . n - normal at the current point
    2429: . numConstants - number of constant parameters
    2430: . constants - constant parameters
    2431: - g0 - output values at the current point

    2433:   Level: intermediate

    2435: .seealso: PetscDSGetBdJacobian()
    2436: @*/
    2437: PetscErrorCode PetscDSSetBdJacobian(PetscDS ds, PetscInt f, PetscInt g,
    2438:                                     void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2439:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2440:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2441:                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    2442:                                     void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2443:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2444:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2445:                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    2446:                                     void (*g2)(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, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    2450:                                     void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2451:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2452:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2453:                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    2454: {
    2462:   PetscWeakFormSetIndexBdJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);
    2463:   return 0;
    2464: }

    2466: /*@
    2467:   PetscDSHasBdJacobianPreconditioner - Signals that boundary Jacobian preconditioner functions have been set

    2469:   Not collective

    2471:   Input Parameter:
    2472: . ds - The PetscDS

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

    2477:   Level: intermediate

    2479: .seealso: PetscDSHasJacobian(), PetscDSSetBdJacobian(), PetscDSGetBdJacobian()
    2480: @*/
    2481: PetscErrorCode PetscDSHasBdJacobianPreconditioner(PetscDS ds, PetscBool *hasBdJacPre)
    2482: {
    2485:   PetscWeakFormHasBdJacobianPreconditioner(ds->wf, hasBdJacPre);
    2486:   return 0;
    2487: }

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

    2492:   Not collective

    2494:   Input Parameters:
    2495: + ds - The PetscDS
    2496: . f  - The test field number
    2497: - g  - The field number

    2499:   Output Parameters:
    2500: + g0 - integrand for the test and basis function term
    2501: . g1 - integrand for the test function and basis function gradient term
    2502: . g2 - integrand for the test function gradient and basis function term
    2503: - g3 - integrand for the test function gradient and basis function gradient term

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

    2507:   \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

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

    2511: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2512: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2513: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2514: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])

    2516: + dim - the spatial dimension
    2517: . Nf - the number of fields
    2518: . NfAux - the number of auxiliary fields
    2519: . uOff - the offset into u[] and u_t[] for each field
    2520: . uOff_x - the offset into u_x[] for each field
    2521: . u - each field evaluated at the current point
    2522: . u_t - the time derivative of each field evaluated at the current point
    2523: . u_x - the gradient of each field evaluated at the current point
    2524: . aOff - the offset into a[] and a_t[] for each auxiliary field
    2525: . aOff_x - the offset into a_x[] for each auxiliary field
    2526: . a - each auxiliary field evaluated at the current point
    2527: . a_t - the time derivative of each auxiliary field evaluated at the current point
    2528: . a_x - the gradient of auxiliary each field evaluated at the current point
    2529: . t - current time
    2530: . u_tShift - the multiplier a for dF/dU_t
    2531: . x - coordinates of the current point
    2532: . n - normal at the current point
    2533: . numConstants - number of constant parameters
    2534: . constants - constant parameters
    2535: - g0 - output values at the current point

    2537:   This is not yet available in Fortran.

    2539:   Level: intermediate

    2541: .seealso: PetscDSSetBdJacobianPreconditioner()
    2542: @*/
    2543: PetscErrorCode PetscDSGetBdJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g,
    2544:                                                   void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2545:                                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2546:                                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2547:                                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    2548:                                                   void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2549:                                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2550:                                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2551:                                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    2552:                                                   void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2553:                                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2554:                                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2555:                                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    2556:                                                   void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2557:                                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2558:                                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2559:                                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    2560: {
    2561:   PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3;
    2562:   PetscInt         n0, n1, n2, n3;

    2567:   PetscWeakFormGetBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);
    2568:   *g0  = tmp0 ? tmp0[0] : NULL;
    2569:   *g1  = tmp1 ? tmp1[0] : NULL;
    2570:   *g2  = tmp2 ? tmp2[0] : NULL;
    2571:   *g3  = tmp3 ? tmp3[0] : NULL;
    2572:   return 0;
    2573: }

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

    2578:   Not collective

    2580:   Input Parameters:
    2581: + ds - The PetscDS
    2582: . f  - The test field number
    2583: . g  - The field number
    2584: . g0 - integrand for the test and basis function term
    2585: . g1 - integrand for the test function and basis function gradient term
    2586: . g2 - integrand for the test function gradient and basis function term
    2587: - g3 - integrand for the test function gradient and basis function gradient term

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

    2591:   \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

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

    2595: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2596: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2597: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2598: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])

    2600: + dim - the spatial dimension
    2601: . Nf - the number of fields
    2602: . NfAux - the number of auxiliary fields
    2603: . uOff - the offset into u[] and u_t[] for each field
    2604: . uOff_x - the offset into u_x[] for each field
    2605: . u - each field evaluated at the current point
    2606: . u_t - the time derivative of each field evaluated at the current point
    2607: . u_x - the gradient of each field evaluated at the current point
    2608: . aOff - the offset into a[] and a_t[] for each auxiliary field
    2609: . aOff_x - the offset into a_x[] for each auxiliary field
    2610: . a - each auxiliary field evaluated at the current point
    2611: . a_t - the time derivative of each auxiliary field evaluated at the current point
    2612: . a_x - the gradient of auxiliary each field evaluated at the current point
    2613: . t - current time
    2614: . u_tShift - the multiplier a for dF/dU_t
    2615: . x - coordinates of the current point
    2616: . n - normal at the current point
    2617: . numConstants - number of constant parameters
    2618: . constants - constant parameters
    2619: - g0 - output values at the current point

    2621:   This is not yet available in Fortran.

    2623:   Level: intermediate

    2625: .seealso: PetscDSGetBdJacobianPreconditioner()
    2626: @*/
    2627: PetscErrorCode PetscDSSetBdJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g,
    2628:                                                   void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2629:                                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2630:                                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2631:                                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    2632:                                                   void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2633:                                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2634:                                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2635:                                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    2636:                                                   void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2637:                                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2638:                                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2639:                                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    2640:                                                   void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2641:                                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2642:                                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2643:                                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    2644: {
    2652:   PetscWeakFormSetIndexBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);
    2653:   return 0;
    2654: }

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

    2659:   Not collective

    2661:   Input Parameters:
    2662: + prob - The PetscDS
    2663: - f    - The test field number

    2665:   Output Parameters:
    2666: + exactSol - exact solution for the test field
    2667: - exactCtx - exact solution context

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

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

    2673: + dim - the spatial dimension
    2674: . t - current time
    2675: . x - coordinates of the current point
    2676: . Nc - the number of field components
    2677: . u - the solution field evaluated at the current point
    2678: - ctx - a user context

    2680:   Level: intermediate

    2682: .seealso: PetscDSSetExactSolution(), PetscDSGetExactSolutionTimeDerivative()
    2683: @*/
    2684: PetscErrorCode PetscDSGetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx)
    2685: {
    2690:   return 0;
    2691: }

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

    2696:   Not collective

    2698:   Input Parameters:
    2699: + prob - The PetscDS
    2700: . f    - The test field number
    2701: . sol  - solution function for the test fields
    2702: - ctx  - solution context or NULL

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

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

    2708: + dim - the spatial dimension
    2709: . t - current time
    2710: . x - coordinates of the current point
    2711: . Nc - the number of field components
    2712: . u - the solution field evaluated at the current point
    2713: - ctx - a user context

    2715:   Level: intermediate

    2717: .seealso: PetscDSGetExactSolution()
    2718: @*/
    2719: PetscErrorCode PetscDSSetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx)
    2720: {
    2723:   PetscDSEnlarge_Static(prob, f+1);
    2726:   return 0;
    2727: }

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

    2732:   Not collective

    2734:   Input Parameters:
    2735: + prob - The PetscDS
    2736: - f    - The test field number

    2738:   Output Parameters:
    2739: + exactSol - time derivative of the exact solution for the test field
    2740: - exactCtx - time derivative of the exact solution context

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

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

    2746: + dim - the spatial dimension
    2747: . t - current time
    2748: . x - coordinates of the current point
    2749: . Nc - the number of field components
    2750: . u - the solution field evaluated at the current point
    2751: - ctx - a user context

    2753:   Level: intermediate

    2755: .seealso: PetscDSSetExactSolutionTimeDerivative(), PetscDSGetExactSolution()
    2756: @*/
    2757: PetscErrorCode PetscDSGetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx)
    2758: {
    2763:   return 0;
    2764: }

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

    2769:   Not collective

    2771:   Input Parameters:
    2772: + prob - The PetscDS
    2773: . f    - The test field number
    2774: . sol  - time derivative of the solution function for the test fields
    2775: - ctx  - time derivative of the solution context or NULL

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

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

    2781: + dim - the spatial dimension
    2782: . t - current time
    2783: . x - coordinates of the current point
    2784: . Nc - the number of field components
    2785: . u - the solution field evaluated at the current point
    2786: - ctx - a user context

    2788:   Level: intermediate

    2790: .seealso: PetscDSGetExactSolutionTimeDerivative(), PetscDSSetExactSolution()
    2791: @*/
    2792: PetscErrorCode PetscDSSetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx)
    2793: {
    2796:   PetscDSEnlarge_Static(prob, f+1);
    2799:   return 0;
    2800: }

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

    2805:   Not collective

    2807:   Input Parameter:
    2808: . prob - The PetscDS object

    2810:   Output Parameters:
    2811: + numConstants - The number of constants
    2812: - constants    - The array of constants, NULL if there are none

    2814:   Level: intermediate

    2816: .seealso: PetscDSSetConstants(), PetscDSCreate()
    2817: @*/
    2818: PetscErrorCode PetscDSGetConstants(PetscDS prob, PetscInt *numConstants, const PetscScalar *constants[])
    2819: {
    2823:   return 0;
    2824: }

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

    2829:   Not collective

    2831:   Input Parameters:
    2832: + prob         - The PetscDS object
    2833: . numConstants - The number of constants
    2834: - constants    - The array of constants, NULL if there are none

    2836:   Level: intermediate

    2838: .seealso: PetscDSGetConstants(), PetscDSCreate()
    2839: @*/
    2840: PetscErrorCode PetscDSSetConstants(PetscDS prob, PetscInt numConstants, PetscScalar constants[])
    2841: {
    2843:   if (numConstants != prob->numConstants) {
    2844:     PetscFree(prob->constants);
    2845:     prob->numConstants = numConstants;
    2846:     if (prob->numConstants) {
    2847:       PetscMalloc1(prob->numConstants, &prob->constants);
    2848:     } else {
    2849:       prob->constants = NULL;
    2850:     }
    2851:   }
    2852:   if (prob->numConstants) {
    2854:     PetscArraycpy(prob->constants, constants, prob->numConstants);
    2855:   }
    2856:   return 0;
    2857: }

    2859: /*@
    2860:   PetscDSGetFieldIndex - Returns the index of the given field

    2862:   Not collective

    2864:   Input Parameters:
    2865: + prob - The PetscDS object
    2866: - disc - The discretization object

    2868:   Output Parameter:
    2869: . f - The field number

    2871:   Level: beginner

    2873: .seealso: PetscGetDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    2874: @*/
    2875: PetscErrorCode PetscDSGetFieldIndex(PetscDS prob, PetscObject disc, PetscInt *f)
    2876: {
    2877:   PetscInt g;

    2881:   *f = -1;
    2882:   for (g = 0; g < prob->Nf; ++g) {if (disc == prob->disc[g]) break;}
    2884:   *f = g;
    2885:   return 0;
    2886: }

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

    2891:   Not collective

    2893:   Input Parameters:
    2894: + prob - The PetscDS object
    2895: - f - The field number

    2897:   Output Parameter:
    2898: . size - The size

    2900:   Level: beginner

    2902: .seealso: PetscDSGetFieldOffset(), PetscDSGetNumFields(), PetscDSCreate()
    2903: @*/
    2904: PetscErrorCode PetscDSGetFieldSize(PetscDS prob, PetscInt f, PetscInt *size)
    2905: {
    2909:   PetscDSSetUp(prob);
    2910:   *size = prob->Nb[f];
    2911:   return 0;
    2912: }

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

    2917:   Not collective

    2919:   Input Parameters:
    2920: + prob - The PetscDS object
    2921: - f - The field number

    2923:   Output Parameter:
    2924: . off - The offset

    2926:   Level: beginner

    2928: .seealso: PetscDSGetFieldSize(), PetscDSGetNumFields(), PetscDSCreate()
    2929: @*/
    2930: PetscErrorCode PetscDSGetFieldOffset(PetscDS prob, PetscInt f, PetscInt *off)
    2931: {
    2932:   PetscInt       size, g;

    2937:   *off = 0;
    2938:   for (g = 0; g < f; ++g) {
    2939:     PetscDSGetFieldSize(prob, g, &size);
    2940:     *off += size;
    2941:   }
    2942:   return 0;
    2943: }

    2945: /*@
    2946:   PetscDSGetFieldOffsetCohesive - Returns the offset of the given field in the full space basis on a cohesive cell

    2948:   Not collective

    2950:   Input Parameters:
    2951: + prob - The PetscDS object
    2952: - f - The field number

    2954:   Output Parameter:
    2955: . off - The offset

    2957:   Level: beginner

    2959: .seealso: PetscDSGetFieldSize(), PetscDSGetNumFields(), PetscDSCreate()
    2960: @*/
    2961: PetscErrorCode PetscDSGetFieldOffsetCohesive(PetscDS ds, PetscInt f, PetscInt *off)
    2962: {
    2963:   PetscInt       size, g;

    2968:   *off = 0;
    2969:   for (g = 0; g < f; ++g) {
    2970:     PetscBool cohesive;

    2972:     PetscDSGetCohesive(ds, g, &cohesive);
    2973:     PetscDSGetFieldSize(ds, g, &size);
    2974:     *off += cohesive ? size : size*2;
    2975:   }
    2976:   return 0;
    2977: }

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

    2982:   Not collective

    2984:   Input Parameter:
    2985: . prob - The PetscDS object

    2987:   Output Parameter:
    2988: . dimensions - The number of dimensions

    2990:   Level: beginner

    2992: .seealso: PetscDSGetComponentOffsets(), PetscDSGetNumFields(), PetscDSCreate()
    2993: @*/
    2994: PetscErrorCode PetscDSGetDimensions(PetscDS prob, PetscInt *dimensions[])
    2995: {
    2997:   PetscDSSetUp(prob);
    2999:   *dimensions = prob->Nb;
    3000:   return 0;
    3001: }

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

    3006:   Not collective

    3008:   Input Parameter:
    3009: . prob - The PetscDS object

    3011:   Output Parameter:
    3012: . components - The number of components

    3014:   Level: beginner

    3016: .seealso: PetscDSGetComponentOffsets(), PetscDSGetNumFields(), PetscDSCreate()
    3017: @*/
    3018: PetscErrorCode PetscDSGetComponents(PetscDS prob, PetscInt *components[])
    3019: {
    3021:   PetscDSSetUp(prob);
    3023:   *components = prob->Nc;
    3024:   return 0;
    3025: }

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

    3030:   Not collective

    3032:   Input Parameters:
    3033: + prob - The PetscDS object
    3034: - f - The field number

    3036:   Output Parameter:
    3037: . off - The offset

    3039:   Level: beginner

    3041: .seealso: PetscDSGetNumFields(), PetscDSCreate()
    3042: @*/
    3043: PetscErrorCode PetscDSGetComponentOffset(PetscDS prob, PetscInt f, PetscInt *off)
    3044: {
    3048:   PetscDSSetUp(prob);
    3049:   *off = prob->off[f];
    3050:   return 0;
    3051: }

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

    3056:   Not collective

    3058:   Input Parameter:
    3059: . prob - The PetscDS object

    3061:   Output Parameter:
    3062: . offsets - The offsets

    3064:   Level: beginner

    3066: .seealso: PetscDSGetNumFields(), PetscDSCreate()
    3067: @*/
    3068: PetscErrorCode PetscDSGetComponentOffsets(PetscDS prob, PetscInt *offsets[])
    3069: {
    3072:   PetscDSSetUp(prob);
    3073:   *offsets = prob->off;
    3074:   return 0;
    3075: }

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

    3080:   Not collective

    3082:   Input Parameter:
    3083: . prob - The PetscDS object

    3085:   Output Parameter:
    3086: . offsets - The offsets

    3088:   Level: beginner

    3090: .seealso: PetscDSGetNumFields(), PetscDSCreate()
    3091: @*/
    3092: PetscErrorCode PetscDSGetComponentDerivativeOffsets(PetscDS prob, PetscInt *offsets[])
    3093: {
    3096:   PetscDSSetUp(prob);
    3097:   *offsets = prob->offDer;
    3098:   return 0;
    3099: }

    3101: /*@
    3102:   PetscDSGetComponentOffsetsCohesive - Returns the offset of each field on an evaluation point

    3104:   Not collective

    3106:   Input Parameters:
    3107: + ds - The PetscDS object
    3108: - s  - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive

    3110:   Output Parameter:
    3111: . offsets - The offsets

    3113:   Level: beginner

    3115: .seealso: PetscDSGetNumFields(), PetscDSCreate()
    3116: @*/
    3117: PetscErrorCode PetscDSGetComponentOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[])
    3118: {
    3123:   PetscDSSetUp(ds);
    3124:   *offsets = ds->offCohesive[s];
    3125:   return 0;
    3126: }

    3128: /*@
    3129:   PetscDSGetComponentDerivativeOffsetsCohesive - Returns the offset of each field derivative on an evaluation point

    3131:   Not collective

    3133:   Input Parameters:
    3134: + ds - The PetscDS object
    3135: - s  - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive

    3137:   Output Parameter:
    3138: . offsets - The offsets

    3140:   Level: beginner

    3142: .seealso: PetscDSGetNumFields(), PetscDSCreate()
    3143: @*/
    3144: PetscErrorCode PetscDSGetComponentDerivativeOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[])
    3145: {
    3150:   PetscDSSetUp(ds);
    3151:   *offsets = ds->offDerCohesive[s];
    3152:   return 0;
    3153: }

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

    3158:   Not collective

    3160:   Input Parameter:
    3161: . prob - The PetscDS object

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

    3166:   Level: intermediate

    3168: .seealso: PetscDSCreate()
    3169: @*/
    3170: PetscErrorCode PetscDSGetTabulation(PetscDS prob, PetscTabulation *T[])
    3171: {
    3174:   PetscDSSetUp(prob);
    3175:   *T = prob->T;
    3176:   return 0;
    3177: }

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

    3182:   Not collective

    3184:   Input Parameter:
    3185: . prob - The PetscDS object

    3187:   Output Parameter:
    3188: . Tf - The basis function and derivative tabulation on each local face at quadrature points for each and field

    3190:   Level: intermediate

    3192: .seealso: PetscDSGetTabulation(), PetscDSCreate()
    3193: @*/
    3194: PetscErrorCode PetscDSGetFaceTabulation(PetscDS prob, PetscTabulation *Tf[])
    3195: {
    3198:   PetscDSSetUp(prob);
    3199:   *Tf = prob->Tf;
    3200:   return 0;
    3201: }

    3203: PetscErrorCode PetscDSGetEvaluationArrays(PetscDS prob, PetscScalar **u, PetscScalar **u_t, PetscScalar **u_x)
    3204: {
    3206:   PetscDSSetUp(prob);
    3210:   return 0;
    3211: }

    3213: PetscErrorCode PetscDSGetWeakFormArrays(PetscDS prob, PetscScalar **f0, PetscScalar **f1, PetscScalar **g0, PetscScalar **g1, PetscScalar **g2, PetscScalar **g3)
    3214: {
    3216:   PetscDSSetUp(prob);
    3223:   return 0;
    3224: }

    3226: PetscErrorCode PetscDSGetWorkspace(PetscDS prob, PetscReal **x, PetscScalar **basisReal, PetscScalar **basisDerReal, PetscScalar **testReal, PetscScalar **testDerReal)
    3227: {
    3229:   PetscDSSetUp(prob);
    3235:   return 0;
    3236: }

    3238: /*@C
    3239:   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 performed, using the kernels from PetscDSSetBdResidual().

    3241:   Collective on ds

    3243:   Input Parameters:
    3244: + ds       - The PetscDS object
    3245: . type     - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
    3246: . name     - The BC name
    3247: . label    - The label defining constrained points
    3248: . Nv       - The number of DMLabel values for constrained points
    3249: . values   - An array of label values for constrained points
    3250: . field    - The field to constrain
    3251: . Nc       - The number of constrained field components (0 will constrain all fields)
    3252: . comps    - An array of constrained component numbers
    3253: . bcFunc   - A pointwise function giving boundary values
    3254: . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL
    3255: - ctx      - An optional user context for bcFunc

    3257:   Output Parameters:
    3258: - bd       - The boundary number

    3260:   Options Database Keys:
    3261: + -bc_<boundary name> <num> - Overrides the boundary ids
    3262: - -bc_<boundary name>_comp <num> - Overrides the boundary components

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

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

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

    3271: $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    3272: $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    3273: $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    3274: $        PetscReal time, const PetscReal x[], PetscScalar bcval[])

    3276: + dim - the spatial dimension
    3277: . Nf - the number of fields
    3278: . uOff - the offset into u[] and u_t[] for each field
    3279: . uOff_x - the offset into u_x[] for each field
    3280: . u - each field evaluated at the current point
    3281: . u_t - the time derivative of each field evaluated at the current point
    3282: . u_x - the gradient of each field evaluated at the current point
    3283: . aOff - the offset into a[] and a_t[] for each auxiliary field
    3284: . aOff_x - the offset into a_x[] for each auxiliary field
    3285: . a - each auxiliary field evaluated at the current point
    3286: . a_t - the time derivative of each auxiliary field evaluated at the current point
    3287: . a_x - the gradient of auxiliary each field evaluated at the current point
    3288: . t - current time
    3289: . x - coordinates of the current point
    3290: . numConstants - number of constant parameters
    3291: . constants - constant parameters
    3292: - bcval - output values at the current point

    3294:   Level: developer

    3296: .seealso: PetscDSAddBoundaryByName(), PetscDSGetBoundary(), PetscDSSetResidual(), PetscDSSetBdResidual()
    3297: @*/
    3298: PetscErrorCode PetscDSAddBoundary(PetscDS ds, DMBoundaryConditionType type, const char name[], DMLabel label, PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx, PetscInt *bd)
    3299: {
    3300:   DSBoundary     head = ds->boundary, b;
    3301:   PetscInt       n    = 0;
    3302:   const char    *lname;

    3311:   if (Nc > 0) {
    3312:     PetscInt *fcomps;
    3313:     PetscInt  c;

    3315:     PetscDSGetComponents(ds, &fcomps);
    3317:     for (c = 0; c < Nc; ++c) {
    3319:     }
    3320:   }
    3321:   PetscNew(&b);
    3322:   PetscStrallocpy(name, (char **) &b->name);
    3323:   PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf);
    3324:   PetscWeakFormSetNumFields(b->wf, ds->Nf);
    3325:   PetscMalloc1(Nv, &b->values);
    3326:   if (Nv) PetscArraycpy(b->values, values, Nv);
    3327:   PetscMalloc1(Nc, &b->comps);
    3328:   if (Nc) PetscArraycpy(b->comps, comps, Nc);
    3329:   PetscObjectGetName((PetscObject) label, &lname);
    3330:   PetscStrallocpy(lname, (char **) &b->lname);
    3331:   b->type   = type;
    3332:   b->label  = label;
    3333:   b->Nv     = Nv;
    3334:   b->field  = field;
    3335:   b->Nc     = Nc;
    3336:   b->func   = bcFunc;
    3337:   b->func_t = bcFunc_t;
    3338:   b->ctx    = ctx;
    3339:   b->next   = NULL;
    3340:   /* Append to linked list so that we can preserve the order */
    3341:   if (!head) ds->boundary = b;
    3342:   while (head) {
    3343:     if (!head->next) {
    3344:       head->next = b;
    3345:       head       = b;
    3346:     }
    3347:     head = head->next;
    3348:     ++n;
    3349:   }
    3351:   return 0;
    3352: }

    3354: /*@C
    3355:   PetscDSAddBoundaryByName - 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 performed, using the kernels from PetscDSSetBdResidual().

    3357:   Collective on ds

    3359:   Input Parameters:
    3360: + ds       - The PetscDS object
    3361: . type     - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
    3362: . name     - The BC name
    3363: . lname    - The naem of the label defining constrained points
    3364: . Nv       - The number of DMLabel values for constrained points
    3365: . values   - An array of label values for constrained points
    3366: . field    - The field to constrain
    3367: . Nc       - The number of constrained field components (0 will constrain all fields)
    3368: . comps    - An array of constrained component numbers
    3369: . bcFunc   - A pointwise function giving boundary values
    3370: . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL
    3371: - ctx      - An optional user context for bcFunc

    3373:   Output Parameters:
    3374: - bd       - The boundary number

    3376:   Options Database Keys:
    3377: + -bc_<boundary name> <num> - Overrides the boundary ids
    3378: - -bc_<boundary name>_comp <num> - Overrides the boundary components

    3380:   Note:
    3381:   This function should only be used with DMForest currently, since labels cannot be defined before the underlygin Plex is built.

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

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

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

    3389: $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    3390: $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    3391: $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    3392: $        PetscReal time, const PetscReal x[], PetscScalar bcval[])

    3394: + dim - the spatial dimension
    3395: . Nf - the number of fields
    3396: . uOff - the offset into u[] and u_t[] for each field
    3397: . uOff_x - the offset into u_x[] for each field
    3398: . u - each field evaluated at the current point
    3399: . u_t - the time derivative of each field evaluated at the current point
    3400: . u_x - the gradient of each field evaluated at the current point
    3401: . aOff - the offset into a[] and a_t[] for each auxiliary field
    3402: . aOff_x - the offset into a_x[] for each auxiliary field
    3403: . a - each auxiliary field evaluated at the current point
    3404: . a_t - the time derivative of each auxiliary field evaluated at the current point
    3405: . a_x - the gradient of auxiliary each field evaluated at the current point
    3406: . t - current time
    3407: . x - coordinates of the current point
    3408: . numConstants - number of constant parameters
    3409: . constants - constant parameters
    3410: - bcval - output values at the current point

    3412:   Level: developer

    3414: .seealso: PetscDSAddBoundary(), PetscDSGetBoundary(), PetscDSSetResidual(), PetscDSSetBdResidual()
    3415: @*/
    3416: PetscErrorCode PetscDSAddBoundaryByName(PetscDS ds, DMBoundaryConditionType type, const char name[], const char lname[], PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx, PetscInt *bd)
    3417: {
    3418:   DSBoundary     head = ds->boundary, b;
    3419:   PetscInt       n    = 0;

    3428:   PetscNew(&b);
    3429:   PetscStrallocpy(name, (char **) &b->name);
    3430:   PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf);
    3431:   PetscWeakFormSetNumFields(b->wf, ds->Nf);
    3432:   PetscMalloc1(Nv, &b->values);
    3433:   if (Nv) PetscArraycpy(b->values, values, Nv);
    3434:   PetscMalloc1(Nc, &b->comps);
    3435:   if (Nc) PetscArraycpy(b->comps, comps, Nc);
    3436:   PetscStrallocpy(lname, (char **) &b->lname);
    3437:   b->type   = type;
    3438:   b->label  = NULL;
    3439:   b->Nv     = Nv;
    3440:   b->field  = field;
    3441:   b->Nc     = Nc;
    3442:   b->func   = bcFunc;
    3443:   b->func_t = bcFunc_t;
    3444:   b->ctx    = ctx;
    3445:   b->next   = NULL;
    3446:   /* Append to linked list so that we can preserve the order */
    3447:   if (!head) ds->boundary = b;
    3448:   while (head) {
    3449:     if (!head->next) {
    3450:       head->next = b;
    3451:       head       = b;
    3452:     }
    3453:     head = head->next;
    3454:     ++n;
    3455:   }
    3457:   return 0;
    3458: }

    3460: /*@C
    3461:   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 performed, using the kernels from PetscDSSetBdResidual().

    3463:   Input Parameters:
    3464: + ds       - The PetscDS object
    3465: . bd       - The boundary condition number
    3466: . type     - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
    3467: . name     - The BC name
    3468: . label    - The label defining constrained points
    3469: . Nv       - The number of DMLabel ids for constrained points
    3470: . values   - An array of ids for constrained points
    3471: . field    - The field to constrain
    3472: . Nc       - The number of constrained field components
    3473: . comps    - An array of constrained component numbers
    3474: . bcFunc   - A pointwise function giving boundary values
    3475: . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL
    3476: - ctx      - An optional user context for bcFunc

    3478:   Note:
    3479:   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.

    3481:   Level: developer

    3483: .seealso: PetscDSAddBoundary(), PetscDSGetBoundary(), PetscDSGetNumBoundary()
    3484: @*/
    3485: PetscErrorCode PetscDSUpdateBoundary(PetscDS ds, PetscInt bd, DMBoundaryConditionType type, const char name[], DMLabel label, PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx)
    3486: {
    3487:   DSBoundary     b = ds->boundary;
    3488:   PetscInt       n = 0;

    3491:   while (b) {
    3492:     if (n == bd) break;
    3493:     b = b->next;
    3494:     ++n;
    3495:   }
    3497:   if (name) {
    3498:     PetscFree(b->name);
    3499:     PetscStrallocpy(name, (char **) &b->name);
    3500:   }
    3501:   b->type = type;
    3502:   if (label) {
    3503:     const char *name;

    3505:     b->label = label;
    3506:     PetscFree(b->lname);
    3507:     PetscObjectGetName((PetscObject) label, &name);
    3508:     PetscStrallocpy(name, (char **) &b->lname);
    3509:   }
    3510:   if (Nv >= 0) {
    3511:     b->Nv = Nv;
    3512:     PetscFree(b->values);
    3513:     PetscMalloc1(Nv, &b->values);
    3514:     if (Nv) PetscArraycpy(b->values, values, Nv);
    3515:   }
    3516:   if (field >= 0) b->field = field;
    3517:   if (Nc >= 0) {
    3518:     b->Nc = Nc;
    3519:     PetscFree(b->comps);
    3520:     PetscMalloc1(Nc, &b->comps);
    3521:     if (Nc) PetscArraycpy(b->comps, comps, Nc);
    3522:   }
    3523:   if (bcFunc)   b->func   = bcFunc;
    3524:   if (bcFunc_t) b->func_t = bcFunc_t;
    3525:   if (ctx)      b->ctx    = ctx;
    3526:   return 0;
    3527: }

    3529: /*@
    3530:   PetscDSGetNumBoundary - Get the number of registered BC

    3532:   Input Parameters:
    3533: . ds - The PetscDS object

    3535:   Output Parameters:
    3536: . numBd - The number of BC

    3538:   Level: intermediate

    3540: .seealso: PetscDSAddBoundary(), PetscDSGetBoundary()
    3541: @*/
    3542: PetscErrorCode PetscDSGetNumBoundary(PetscDS ds, PetscInt *numBd)
    3543: {
    3544:   DSBoundary b = ds->boundary;

    3548:   *numBd = 0;
    3549:   while (b) {++(*numBd); b = b->next;}
    3550:   return 0;
    3551: }

    3553: /*@C
    3554:   PetscDSGetBoundary - Gets a boundary condition to the model

    3556:   Input Parameters:
    3557: + ds          - The PetscDS object
    3558: - bd          - The BC number

    3560:   Output Parameters:
    3561: + wf       - The PetscWeakForm holding the pointwise functions
    3562: . type     - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
    3563: . name     - The BC name
    3564: . label    - The label defining constrained points
    3565: . Nv       - The number of DMLabel ids for constrained points
    3566: . values   - An array of ids for constrained points
    3567: . field    - The field to constrain
    3568: . Nc       - The number of constrained field components
    3569: . comps    - An array of constrained component numbers
    3570: . bcFunc   - A pointwise function giving boundary values
    3571: . bcFunc_t - A pointwise function giving the time derivative of the boundary values
    3572: - ctx      - An optional user context for bcFunc

    3574:   Options Database Keys:
    3575: + -bc_<boundary name> <num> - Overrides the boundary ids
    3576: - -bc_<boundary name>_comp <num> - Overrides the boundary components

    3578:   Level: developer

    3580: .seealso: PetscDSAddBoundary()
    3581: @*/
    3582: PetscErrorCode PetscDSGetBoundary(PetscDS ds, PetscInt bd, PetscWeakForm *wf, DMBoundaryConditionType *type, const char *name[], DMLabel *label, PetscInt *Nv, const PetscInt *values[], PetscInt *field, PetscInt *Nc, const PetscInt *comps[], void (**func)(void), void (**func_t)(void), void **ctx)
    3583: {
    3584:   DSBoundary b = ds->boundary;
    3585:   PetscInt   n = 0;

    3588:   while (b) {
    3589:     if (n == bd) break;
    3590:     b = b->next;
    3591:     ++n;
    3592:   }
    3594:   if (wf) {
    3596:     *wf = b->wf;
    3597:   }
    3598:   if (type) {
    3600:     *type = b->type;
    3601:   }
    3602:   if (name) {
    3604:     *name = b->name;
    3605:   }
    3606:   if (label) {
    3608:     *label = b->label;
    3609:   }
    3610:   if (Nv) {
    3612:     *Nv = b->Nv;
    3613:   }
    3614:   if (values) {
    3616:     *values = b->values;
    3617:   }
    3618:   if (field) {
    3620:     *field = b->field;
    3621:   }
    3622:   if (Nc) {
    3624:     *Nc = b->Nc;
    3625:   }
    3626:   if (comps) {
    3628:     *comps = b->comps;
    3629:   }
    3630:   if (func) {
    3632:     *func = b->func;
    3633:   }
    3634:   if (func_t) {
    3636:     *func_t = b->func_t;
    3637:   }
    3638:   if (ctx) {
    3640:     *ctx = b->ctx;
    3641:   }
    3642:   return 0;
    3643: }

    3645: static PetscErrorCode DSBoundaryDuplicate_Internal(DSBoundary b, DSBoundary *bNew)
    3646: {
    3647:   PetscNew(bNew);
    3648:   PetscWeakFormCreate(PETSC_COMM_SELF, &(*bNew)->wf);
    3649:   PetscWeakFormCopy(b->wf, (*bNew)->wf);
    3650:   PetscStrallocpy(b->name,(char **) &((*bNew)->name));
    3651:   PetscStrallocpy(b->lname,(char **) &((*bNew)->lname));
    3652:   (*bNew)->type   = b->type;
    3653:   (*bNew)->label  = b->label;
    3654:   (*bNew)->Nv     = b->Nv;
    3655:   PetscMalloc1(b->Nv, &(*bNew)->values);
    3656:   PetscArraycpy((*bNew)->values, b->values, b->Nv);
    3657:   (*bNew)->field  = b->field;
    3658:   (*bNew)->Nc     = b->Nc;
    3659:   PetscMalloc1(b->Nc, &(*bNew)->comps);
    3660:   PetscArraycpy((*bNew)->comps, b->comps, b->Nc);
    3661:   (*bNew)->func   = b->func;
    3662:   (*bNew)->func_t = b->func_t;
    3663:   (*bNew)->ctx    = b->ctx;
    3664:   return 0;
    3665: }

    3667: /*@
    3668:   PetscDSCopyBoundary - Copy all boundary condition objects to the new problem

    3670:   Not collective

    3672:   Input Parameters:
    3673: + ds        - The source PetscDS object
    3674: . numFields - The number of selected fields, or PETSC_DEFAULT for all fields
    3675: - fields    - The selected fields, or NULL for all fields

    3677:   Output Parameter:
    3678: . newds     - The target PetscDS, now with a copy of the boundary conditions

    3680:   Level: intermediate

    3682: .seealso: PetscDSCopyEquations(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
    3683: @*/
    3684: PetscErrorCode PetscDSCopyBoundary(PetscDS ds, PetscInt numFields, const PetscInt fields[], PetscDS newds)
    3685: {
    3686:   DSBoundary     b, *lastnext;

    3690:   if (ds == newds) return 0;
    3691:   PetscDSDestroyBoundary(newds);
    3692:   lastnext = &(newds->boundary);
    3693:   for (b = ds->boundary; b; b = b->next) {
    3694:     DSBoundary bNew;
    3695:     PetscInt   fieldNew = -1;

    3697:     if (numFields > 0 && fields) {
    3698:       PetscInt f;

    3700:       for (f = 0; f < numFields; ++f) if (b->field == fields[f]) break;
    3701:       if (f == numFields) continue;
    3702:       fieldNew = f;
    3703:     }
    3704:     DSBoundaryDuplicate_Internal(b, &bNew);
    3705:     bNew->field = fieldNew < 0 ? b->field : fieldNew;
    3706:     *lastnext = bNew;
    3707:     lastnext  = &(bNew->next);
    3708:   }
    3709:   return 0;
    3710: }

    3712: /*@
    3713:   PetscDSDestroyBoundary - Remove all DMBoundary objects from the PetscDS

    3715:   Not collective

    3717:   Input Parameter:
    3718: . ds - The PetscDS object

    3720:   Level: intermediate

    3722: .seealso: PetscDSCopyBoundary(), PetscDSCopyEquations()
    3723: @*/
    3724: PetscErrorCode PetscDSDestroyBoundary(PetscDS ds)
    3725: {
    3726:   DSBoundary     next = ds->boundary;

    3728:   while (next) {
    3729:     DSBoundary b = next;

    3731:     next = b->next;
    3732:     PetscWeakFormDestroy(&b->wf);
    3733:     PetscFree(b->name);
    3734:     PetscFree(b->lname);
    3735:     PetscFree(b->values);
    3736:     PetscFree(b->comps);
    3737:     PetscFree(b);
    3738:   }
    3739:   return 0;
    3740: }

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

    3745:   Not collective

    3747:   Input Parameters:
    3748: + prob - The PetscDS object
    3749: . numFields - Number of new fields
    3750: - fields - Old field number for each new field

    3752:   Output Parameter:
    3753: . newprob - The PetscDS copy

    3755:   Level: intermediate

    3757: .seealso: PetscDSSelectEquations(), PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
    3758: @*/
    3759: PetscErrorCode PetscDSSelectDiscretizations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob)
    3760: {
    3761:   PetscInt       Nf, Nfn, fn;

    3766:   PetscDSGetNumFields(prob, &Nf);
    3767:   PetscDSGetNumFields(newprob, &Nfn);
    3768:   numFields = numFields < 0 ? Nf : numFields;
    3769:   for (fn = 0; fn < numFields; ++fn) {
    3770:     const PetscInt f = fields ? fields[fn] : fn;
    3771:     PetscObject    disc;

    3773:     if (f >= Nf) continue;
    3774:     PetscDSGetDiscretization(prob, f, &disc);
    3775:     PetscDSSetDiscretization(newprob, fn, disc);
    3776:   }
    3777:   return 0;
    3778: }

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

    3783:   Not collective

    3785:   Input Parameters:
    3786: + prob - The PetscDS object
    3787: . numFields - Number of new fields
    3788: - fields - Old field number for each new field

    3790:   Output Parameter:
    3791: . newprob - The PetscDS copy

    3793:   Level: intermediate

    3795: .seealso: PetscDSSelectDiscretizations(), PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
    3796: @*/
    3797: PetscErrorCode PetscDSSelectEquations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob)
    3798: {
    3799:   PetscInt       Nf, Nfn, fn, gn;

    3804:   PetscDSGetNumFields(prob, &Nf);
    3805:   PetscDSGetNumFields(newprob, &Nfn);
    3807:   for (fn = 0; fn < numFields; ++fn) {
    3808:     const PetscInt   f = fields ? fields[fn] : fn;
    3809:     PetscPointFunc   obj;
    3810:     PetscPointFunc   f0, f1;
    3811:     PetscBdPointFunc f0Bd, f1Bd;
    3812:     PetscRiemannFunc r;

    3814:     if (f >= Nf) continue;
    3815:     PetscDSGetObjective(prob, f, &obj);
    3816:     PetscDSGetResidual(prob, f, &f0, &f1);
    3817:     PetscDSGetBdResidual(prob, f, &f0Bd, &f1Bd);
    3818:     PetscDSGetRiemannSolver(prob, f, &r);
    3819:     PetscDSSetObjective(newprob, fn, obj);
    3820:     PetscDSSetResidual(newprob, fn, f0, f1);
    3821:     PetscDSSetBdResidual(newprob, fn, f0Bd, f1Bd);
    3822:     PetscDSSetRiemannSolver(newprob, fn, r);
    3823:     for (gn = 0; gn < numFields; ++gn) {
    3824:       const PetscInt  g = fields ? fields[gn] : gn;
    3825:       PetscPointJac   g0, g1, g2, g3;
    3826:       PetscPointJac   g0p, g1p, g2p, g3p;
    3827:       PetscBdPointJac g0Bd, g1Bd, g2Bd, g3Bd;

    3829:       if (g >= Nf) continue;
    3830:       PetscDSGetJacobian(prob, f, g, &g0, &g1, &g2, &g3);
    3831:       PetscDSGetJacobianPreconditioner(prob, f, g, &g0p, &g1p, &g2p, &g3p);
    3832:       PetscDSGetBdJacobian(prob, f, g, &g0Bd, &g1Bd, &g2Bd, &g3Bd);
    3833:       PetscDSSetJacobian(newprob, fn, gn, g0, g1, g2, g3);
    3834:       PetscDSSetJacobianPreconditioner(newprob, fn, gn, g0p, g1p, g2p, g3p);
    3835:       PetscDSSetBdJacobian(newprob, fn, gn, g0Bd, g1Bd, g2Bd, g3Bd);
    3836:     }
    3837:   }
    3838:   return 0;
    3839: }

    3841: /*@
    3842:   PetscDSCopyEquations - Copy all pointwise function pointers to the new problem

    3844:   Not collective

    3846:   Input Parameter:
    3847: . prob - The PetscDS object

    3849:   Output Parameter:
    3850: . newprob - The PetscDS copy

    3852:   Level: intermediate

    3854: .seealso: PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
    3855: @*/
    3856: PetscErrorCode PetscDSCopyEquations(PetscDS prob, PetscDS newprob)
    3857: {
    3858:   PetscWeakForm  wf, newwf;
    3859:   PetscInt       Nf, Ng;

    3863:   PetscDSGetNumFields(prob, &Nf);
    3864:   PetscDSGetNumFields(newprob, &Ng);
    3866:   PetscDSGetWeakForm(prob, &wf);
    3867:   PetscDSGetWeakForm(newprob, &newwf);
    3868:   PetscWeakFormCopy(wf, newwf);
    3869:   return 0;
    3870: }

    3872: /*@
    3873:   PetscDSCopyConstants - Copy all constants to the new problem

    3875:   Not collective

    3877:   Input Parameter:
    3878: . prob - The PetscDS object

    3880:   Output Parameter:
    3881: . newprob - The PetscDS copy

    3883:   Level: intermediate

    3885: .seealso: PetscDSCopyBoundary(), PetscDSCopyEquations(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
    3886: @*/
    3887: PetscErrorCode PetscDSCopyConstants(PetscDS prob, PetscDS newprob)
    3888: {
    3889:   PetscInt           Nc;
    3890:   const PetscScalar *constants;

    3894:   PetscDSGetConstants(prob, &Nc, &constants);
    3895:   PetscDSSetConstants(newprob, Nc, (PetscScalar *) constants);
    3896:   return 0;
    3897: }

    3899: /*@
    3900:   PetscDSCopyExactSolutions - Copy all exact solutions to the new problem

    3902:   Not collective

    3904:   Input Parameter:
    3905: . ds - The PetscDS object

    3907:   Output Parameter:
    3908: . newds - The PetscDS copy

    3910:   Level: intermediate

    3912: .seealso: PetscDSCopyBoundary(), PetscDSCopyEquations(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
    3913: @*/
    3914: PetscErrorCode PetscDSCopyExactSolutions(PetscDS ds, PetscDS newds)
    3915: {
    3916:   PetscSimplePointFunc sol;
    3917:   void                *ctx;
    3918:   PetscInt             Nf, f;

    3922:   PetscDSGetNumFields(ds, &Nf);
    3923:   for (f = 0; f < Nf; ++f) {
    3924:     PetscDSGetExactSolution(ds,    f, &sol, &ctx);
    3925:     PetscDSSetExactSolution(newds, f,  sol,  ctx);
    3926:     PetscDSGetExactSolutionTimeDerivative(ds,    f, &sol, &ctx);
    3927:     PetscDSSetExactSolutionTimeDerivative(newds, f,  sol,  ctx);
    3928:   }
    3929:   return 0;
    3930: }

    3932: PetscErrorCode PetscDSGetHeightSubspace(PetscDS prob, PetscInt height, PetscDS *subprob)
    3933: {
    3934:   PetscInt       dim, Nf, f;

    3938:   if (height == 0) {*subprob = prob; return 0;}
    3939:   PetscDSGetNumFields(prob, &Nf);
    3940:   PetscDSGetSpatialDimension(prob, &dim);
    3942:   if (!prob->subprobs) PetscCalloc1(dim, &prob->subprobs);
    3943:   if (!prob->subprobs[height-1]) {
    3944:     PetscInt cdim;

    3946:     PetscDSCreate(PetscObjectComm((PetscObject) prob), &prob->subprobs[height-1]);
    3947:     PetscDSGetCoordinateDimension(prob, &cdim);
    3948:     PetscDSSetCoordinateDimension(prob->subprobs[height-1], cdim);
    3949:     for (f = 0; f < Nf; ++f) {
    3950:       PetscFE      subfe;
    3951:       PetscObject  obj;
    3952:       PetscClassId id;

    3954:       PetscDSGetDiscretization(prob, f, &obj);
    3955:       PetscObjectGetClassId(obj, &id);
    3956:       if (id == PETSCFE_CLASSID) PetscFEGetHeightSubspace((PetscFE) obj, height, &subfe);
    3957:       else SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unsupported discretization type for field %d", f);
    3958:       PetscDSSetDiscretization(prob->subprobs[height-1], f, (PetscObject) subfe);
    3959:     }
    3960:   }
    3961:   *subprob = prob->subprobs[height-1];
    3962:   return 0;
    3963: }

    3965: PetscErrorCode PetscDSGetDiscType_Internal(PetscDS ds, PetscInt f, PetscDiscType *disctype)
    3966: {
    3967:   PetscObject    obj;
    3968:   PetscClassId   id;
    3969:   PetscInt       Nf;

    3973:   *disctype = PETSC_DISC_NONE;
    3974:   PetscDSGetNumFields(ds, &Nf);
    3976:   PetscDSGetDiscretization(ds, f, &obj);
    3977:   if (obj) {
    3978:     PetscObjectGetClassId(obj, &id);
    3979:     if (id == PETSCFE_CLASSID) *disctype = PETSC_DISC_FE;
    3980:     else                       *disctype = PETSC_DISC_FV;
    3981:   }
    3982:   return 0;
    3983: }

    3985: static PetscErrorCode PetscDSDestroy_Basic(PetscDS ds)
    3986: {
    3987:   PetscFree(ds->data);
    3988:   return 0;
    3989: }

    3991: static PetscErrorCode PetscDSInitialize_Basic(PetscDS ds)
    3992: {
    3993:   ds->ops->setfromoptions = NULL;
    3994:   ds->ops->setup          = NULL;
    3995:   ds->ops->view           = NULL;
    3996:   ds->ops->destroy        = PetscDSDestroy_Basic;
    3997:   return 0;
    3998: }

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

    4003:   Level: intermediate

    4005: .seealso: PetscDSType, PetscDSCreate(), PetscDSSetType()
    4006: M*/

    4008: PETSC_EXTERN PetscErrorCode PetscDSCreate_Basic(PetscDS ds)
    4009: {
    4010:   PetscDS_Basic *b;

    4013:   PetscNewLog(ds, &b);
    4014:   ds->data = b;

    4016:   PetscDSInitialize_Basic(ds);
    4017:   return 0;
    4018: }