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

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

      3: PetscClassId PETSCDS_CLASSID = 0;

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

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

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

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

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

     24:   Not Collective

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

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

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

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

     48:   Level: advanced

     50:    Not available from Fortran

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

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

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

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

     67:   Collective on prob

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

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

     76:   Level: intermediate

     78:    Not available from Fortran

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

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

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

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

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

    109:   Not Collective

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

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

    117:   Level: intermediate

    119:    Not available from Fortran

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

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

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

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

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

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

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

    228: /*@C
    229:    PetscDSViewFromOptions - View from Options

    231:    Collective on PetscDS

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

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

    247:   PetscObjectViewFromOptions((PetscObject)A,obj,name);
    248:   return(0);
    249: }

    251: /*@C
    252:   PetscDSView - Views a PetscDS

    254:   Collective on prob

    256:   Input Parameter:
    257: + prob - the PetscDS object to view
    258: - v  - the viewer

    260:   Level: developer

    262: .seealso PetscDSDestroy()
    263: @*/
    264: PetscErrorCode PetscDSView(PetscDS prob, PetscViewer v)
    265: {
    266:   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 and 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;

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

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

    321:     PetscSNPrintf(optname, sizeof(optname), "-bc_%s", b->name);
    322:     PetscMemzero(ids, sizeof(ids));
    323:     PetscOptionsIntArray(optname, "List of boundary IDs", "", ids, &len, &flg);
    324:     if (flg) {
    325:       b->numids = len;
    326:       PetscFree(b->ids);
    327:       PetscMalloc1(len, &b->ids);
    328:       PetscArraycpy(b->ids, ids, len);
    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->numcomps = 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;

    377:   if (prob->setup) return(0);
    378:   /* Calculate sizes */
    379:   PetscDSGetSpatialDimension(prob, &dim);
    380:   PetscDSGetCoordinateDimension(prob, &dimEmbed);
    381:   prob->totDim = prob->totComp = 0;
    382:   PetscMalloc2(Nf,&prob->Nc,Nf,&prob->Nb);
    383:   PetscCalloc2(Nf+1,&prob->off,Nf+1,&prob->offDer);
    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 SETERRQ1(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:     if (q) {PetscQuadratureGetData(q, NULL, NULL, &Nq, NULL, NULL);}
    422:     NqMax          = PetscMax(NqMax, Nq);
    423:     NbMax          = PetscMax(NbMax, Nb);
    424:     NcMax          = PetscMax(NcMax, Nc);
    425:     prob->totDim  += Nb;
    426:     prob->totComp += Nc;
    427:     /* There are two faces for all fields but the cohesive field on a hybrid cell */
    428:     if (prob->isHybrid && (f < Nf-1)) prob->totDim += Nb;
    429:   }
    430:   /* Allocate works space */
    431:   if (prob->isHybrid) NsMax = 2;
    432:   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);
    433:   PetscMalloc5(dimEmbed,&prob->x,NbMax*NcMax,&prob->basisReal,NbMax*NcMax*dimEmbed,&prob->basisDerReal,NbMax*NcMax,&prob->testReal,NbMax*NcMax*dimEmbed,&prob->testDerReal);
    434:   PetscMalloc6(NsMax*NqMax*NcMax,&prob->f0,NsMax*NqMax*NcMax*dimEmbed,&prob->f1,
    435:                       NsMax*NsMax*NqMax*NcMax*NcMax,&prob->g0,NsMax*NsMax*NqMax*NcMax*NcMax*dimEmbed,&prob->g1,
    436:                       NsMax*NsMax*NqMax*NcMax*NcMax*dimEmbed,&prob->g2,NsMax*NsMax*NqMax*NcMax*NcMax*dimEmbed*dimEmbed,&prob->g3);
    437:   if (prob->ops->setup) {(*prob->ops->setup)(prob);}
    438:   prob->setup = PETSC_TRUE;
    439:   return(0);
    440: }

    442: static PetscErrorCode PetscDSDestroyStructs_Static(PetscDS prob)
    443: {

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

    456: static PetscErrorCode PetscDSEnlarge_Static(PetscDS prob, PetscInt NfNew)
    457: {
    458:   PetscObject      *tmpd;
    459:   PetscBool        *tmpi;
    460:   PetscInt         *tmpk;
    461:   PetscPointFunc   *tmpup;
    462:   PetscSimplePointFunc *tmpexactSol,  *tmpexactSol_t;
    463:   void                **tmpexactCtx, **tmpexactCtx_t;
    464:   void            **tmpctx;
    465:   PetscInt          Nf = prob->Nf, f;
    466:   PetscErrorCode    ierr;

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

    506: /*@
    507:   PetscDSDestroy - Destroys a PetscDS object

    509:   Collective on prob

    511:   Input Parameter:
    512: . prob - the PetscDS object to destroy

    514:   Level: developer

    516: .seealso PetscDSView()
    517: @*/
    518: PetscErrorCode PetscDSDestroy(PetscDS *ds)
    519: {
    520:   PetscInt       f;
    521:   DSBoundary     next;

    525:   if (!*ds) return(0);

    528:   if (--((PetscObject)(*ds))->refct > 0) {*ds = NULL; return(0);}
    529:   ((PetscObject) (*ds))->refct = 0;
    530:   if ((*ds)->subprobs) {
    531:     PetscInt dim, d;

    533:     PetscDSGetSpatialDimension(*ds, &dim);
    534:     for (d = 0; d < dim; ++d) {PetscDSDestroy(&(*ds)->subprobs[d]);}
    535:   }
    536:   PetscFree((*ds)->subprobs);
    537:   PetscDSDestroyStructs_Static(*ds);
    538:   for (f = 0; f < (*ds)->Nf; ++f) {
    539:     PetscObjectDereference((*ds)->disc[f]);
    540:   }
    541:   PetscFree3((*ds)->disc, (*ds)->implicit, (*ds)->jetDegree);
    542:   PetscWeakFormDestroy(&(*ds)->wf);
    543:   PetscFree2((*ds)->update,(*ds)->ctx);
    544:   PetscFree4((*ds)->exactSol,(*ds)->exactCtx,(*ds)->exactSol_t,(*ds)->exactCtx_t);
    545:   if ((*ds)->ops->destroy) {(*(*ds)->ops->destroy)(*ds);}
    546:   next = (*ds)->boundary;
    547:   while (next) {
    548:     DSBoundary b = next;

    550:     next = b->next;
    551:     PetscFree(b->comps);
    552:     PetscFree(b->ids);
    553:     PetscFree(b->name);
    554:     PetscFree(b->labelname);
    555:     PetscFree(b);
    556:   }
    557:   PetscFree((*ds)->constants);
    558:   PetscHeaderDestroy(ds);
    559:   return(0);
    560: }

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

    565:   Collective

    567:   Input Parameter:
    568: . comm - The communicator for the PetscDS object

    570:   Output Parameter:
    571: . ds   - The PetscDS object

    573:   Level: beginner

    575: .seealso: PetscDSSetType(), PETSCDSBASIC
    576: @*/
    577: PetscErrorCode PetscDSCreate(MPI_Comm comm, PetscDS *ds)
    578: {
    579:   PetscDS        p;

    584:   *ds  = NULL;
    585:   PetscDSInitializePackage();

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

    589:   p->Nf           = 0;
    590:   p->setup        = PETSC_FALSE;
    591:   p->numConstants = 0;
    592:   p->constants    = NULL;
    593:   p->dimEmbed     = -1;
    594:   p->useJacPre    = PETSC_TRUE;
    595:   PetscWeakFormCreate(comm, &p->wf);

    597:   *ds = p;
    598:   return(0);
    599: }

    601: /*@
    602:   PetscDSGetNumFields - Returns the number of fields in the DS

    604:   Not collective

    606:   Input Parameter:
    607: . prob - The PetscDS object

    609:   Output Parameter:
    610: . Nf - The number of fields

    612:   Level: beginner

    614: .seealso: PetscDSGetSpatialDimension(), PetscDSCreate()
    615: @*/
    616: PetscErrorCode PetscDSGetNumFields(PetscDS prob, PetscInt *Nf)
    617: {
    621:   *Nf = prob->Nf;
    622:   return(0);
    623: }

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

    628:   Not collective

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

    633:   Output Parameter:
    634: . dim - The spatial dimension

    636:   Level: beginner

    638: .seealso: PetscDSGetCoordinateDimension(), PetscDSGetNumFields(), PetscDSCreate()
    639: @*/
    640: PetscErrorCode PetscDSGetSpatialDimension(PetscDS prob, PetscInt *dim)
    641: {

    647:   *dim = 0;
    648:   if (prob->Nf) {
    649:     PetscObject  obj;
    650:     PetscClassId id;

    652:     PetscDSGetDiscretization(prob, 0, &obj);
    653:     if (obj) {
    654:       PetscObjectGetClassId(obj, &id);
    655:       if (id == PETSCFE_CLASSID)      {PetscFEGetSpatialDimension((PetscFE) obj, dim);}
    656:       else if (id == PETSCFV_CLASSID) {PetscFVGetSpatialDimension((PetscFV) obj, dim);}
    657:       else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
    658:     }
    659:   }
    660:   return(0);
    661: }

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

    666:   Not collective

    668:   Input Parameter:
    669: . prob - The PetscDS object

    671:   Output Parameter:
    672: . dimEmbed - The coordinate dimension

    674:   Level: beginner

    676: .seealso: PetscDSSetCoordinateDimension(), PetscDSGetSpatialDimension(), PetscDSGetNumFields(), PetscDSCreate()
    677: @*/
    678: PetscErrorCode PetscDSGetCoordinateDimension(PetscDS prob, PetscInt *dimEmbed)
    679: {
    683:   if (prob->dimEmbed < 0) SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONGSTATE, "No coordinate dimension set for this DS");
    684:   *dimEmbed = prob->dimEmbed;
    685:   return(0);
    686: }

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

    691:   Logically collective on prob

    693:   Input Parameters:
    694: + prob - The PetscDS object
    695: - dimEmbed - The coordinate dimension

    697:   Level: beginner

    699: .seealso: PetscDSGetCoordinateDimension(), PetscDSGetSpatialDimension(), PetscDSGetNumFields(), PetscDSCreate()
    700: @*/
    701: PetscErrorCode PetscDSSetCoordinateDimension(PetscDS prob, PetscInt dimEmbed)
    702: {
    705:   if (dimEmbed < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate dimension must be non-negative, not %D", dimEmbed);
    706:   prob->dimEmbed = dimEmbed;
    707:   return(0);
    708: }

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

    713:   Not collective

    715:   Input Parameter:
    716: . prob - The PetscDS object

    718:   Output Parameter:
    719: . isHybrid - The flag

    721:   Level: developer

    723: .seealso: PetscDSSetHybrid(), PetscDSCreate()
    724: @*/
    725: PetscErrorCode PetscDSGetHybrid(PetscDS prob, PetscBool *isHybrid)
    726: {
    730:   *isHybrid = prob->isHybrid;
    731:   return(0);
    732: }

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

    737:   Not collective

    739:   Input Parameters:
    740: + prob - The PetscDS object
    741: - isHybrid - The flag

    743:   Level: developer

    745: .seealso: PetscDSGetHybrid(), PetscDSCreate()
    746: @*/
    747: PetscErrorCode PetscDSSetHybrid(PetscDS prob, PetscBool isHybrid)
    748: {
    751:   prob->isHybrid = isHybrid;
    752:   return(0);
    753: }

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

    758:   Not collective

    760:   Input Parameter:
    761: . prob - The PetscDS object

    763:   Output Parameter:
    764: . dim - The total problem dimension

    766:   Level: beginner

    768: .seealso: PetscDSGetNumFields(), PetscDSCreate()
    769: @*/
    770: PetscErrorCode PetscDSGetTotalDimension(PetscDS prob, PetscInt *dim)
    771: {

    776:   PetscDSSetUp(prob);
    778:   *dim = prob->totDim;
    779:   return(0);
    780: }

    782: /*@
    783:   PetscDSGetTotalComponents - Returns the total number of components in this system

    785:   Not collective

    787:   Input Parameter:
    788: . prob - The PetscDS object

    790:   Output Parameter:
    791: . dim - The total number of components

    793:   Level: beginner

    795: .seealso: PetscDSGetNumFields(), PetscDSCreate()
    796: @*/
    797: PetscErrorCode PetscDSGetTotalComponents(PetscDS prob, PetscInt *Nc)
    798: {

    803:   PetscDSSetUp(prob);
    805:   *Nc = prob->totComp;
    806:   return(0);
    807: }

    809: /*@
    810:   PetscDSGetDiscretization - Returns the discretization object for the given field

    812:   Not collective

    814:   Input Parameters:
    815: + prob - The PetscDS object
    816: - f - The field number

    818:   Output Parameter:
    819: . disc - The discretization object

    821:   Level: beginner

    823: .seealso: PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    824: @*/
    825: PetscErrorCode PetscDSGetDiscretization(PetscDS prob, PetscInt f, PetscObject *disc)
    826: {
    830:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    831:   *disc = prob->disc[f];
    832:   return(0);
    833: }

    835: /*@
    836:   PetscDSSetDiscretization - Sets the discretization object for the given field

    838:   Not collective

    840:   Input Parameters:
    841: + prob - The PetscDS object
    842: . f - The field number
    843: - disc - The discretization object

    845:   Level: beginner

    847: .seealso: PetscDSGetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    848: @*/
    849: PetscErrorCode PetscDSSetDiscretization(PetscDS prob, PetscInt f, PetscObject disc)
    850: {

    856:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    857:   PetscDSEnlarge_Static(prob, f+1);
    858:   PetscObjectDereference(prob->disc[f]);
    859:   prob->disc[f] = disc;
    860:   PetscObjectReference(disc);
    861:   if (disc) {
    862:     PetscClassId id;

    864:     PetscObjectGetClassId(disc, &id);
    865:     if (id == PETSCFE_CLASSID) {
    866:       PetscDSSetImplicit(prob, f, PETSC_TRUE);
    867:     } else if (id == PETSCFV_CLASSID) {
    868:       PetscDSSetImplicit(prob, f, PETSC_FALSE);
    869:     }
    870:     PetscDSSetJetDegree(prob, f, 1);
    871:   }
    872:   return(0);
    873: }

    875: /*@
    876:   PetscDSGetWeakForm - Returns the weak form object

    878:   Not collective

    880:   Input Parameter:
    881: . ds - The PetscDS object

    883:   Output Parameter:
    884: . wf - The weak form object

    886:   Level: beginner

    888: .seealso: PetscDSSetWeakForm(), PetscDSGetNumFields(), PetscDSCreate()
    889: @*/
    890: PetscErrorCode PetscDSGetWeakForm(PetscDS ds, PetscWeakForm *wf)
    891: {
    895:   *wf = ds->wf;
    896:   return(0);
    897: }

    899: /*@
    900:   PetscDSSetWeakForm - Sets the weak form object

    902:   Not collective

    904:   Input Parameters:
    905: + ds - The PetscDS object
    906: - wf - The weak form object

    908:   Level: beginner

    910: .seealso: PetscDSGetWeakForm(), PetscDSGetNumFields(), PetscDSCreate()
    911: @*/
    912: PetscErrorCode PetscDSSetWeakForm(PetscDS ds, PetscWeakForm wf)
    913: {

    919:   PetscObjectDereference((PetscObject) ds->wf);
    920:   ds->wf = wf;
    921:   PetscObjectReference((PetscObject) wf);
    922:   PetscWeakFormSetNumFields(wf, ds->Nf);
    923:   return(0);
    924: }

    926: /*@
    927:   PetscDSAddDiscretization - Adds a discretization object

    929:   Not collective

    931:   Input Parameters:
    932: + prob - The PetscDS object
    933: - disc - The boundary discretization object

    935:   Level: beginner

    937: .seealso: PetscDSGetDiscretization(), PetscDSSetDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    938: @*/
    939: PetscErrorCode PetscDSAddDiscretization(PetscDS prob, PetscObject disc)
    940: {

    944:   PetscDSSetDiscretization(prob, prob->Nf, disc);
    945:   return(0);
    946: }

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

    951:   Not collective

    953:   Input Parameter:
    954: . prob - The PetscDS object

    956:   Output Parameter:
    957: . q - The quadrature object

    959: Level: intermediate

    961: .seealso: PetscDSSetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    962: @*/
    963: PetscErrorCode PetscDSGetQuadrature(PetscDS prob, PetscQuadrature *q)
    964: {
    965:   PetscObject    obj;
    966:   PetscClassId   id;

    970:   *q = NULL;
    971:   if (!prob->Nf) return(0);
    972:   PetscDSGetDiscretization(prob, 0, &obj);
    973:   PetscObjectGetClassId(obj, &id);
    974:   if      (id == PETSCFE_CLASSID) {PetscFEGetQuadrature((PetscFE) obj, q);}
    975:   else if (id == PETSCFV_CLASSID) {PetscFVGetQuadrature((PetscFV) obj, q);}
    976:   else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
    977:   return(0);
    978: }

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

    983:   Not collective

    985:   Input Parameters:
    986: + prob - The PetscDS object
    987: - f - The field number

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

    992:   Level: developer

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

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

    1009:   Not collective

    1011:   Input Parameters:
    1012: + prob - The PetscDS object
    1013: . f - The field number
    1014: - implicit - The flag indicating what kind of solve to use for this field

    1016:   Level: developer

    1018: .seealso: PetscDSGetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    1019: @*/
    1020: PetscErrorCode PetscDSSetImplicit(PetscDS prob, PetscInt f, PetscBool implicit)
    1021: {
    1024:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    1025:   prob->implicit[f] = implicit;
    1026:   return(0);
    1027: }

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

    1032:   Not collective

    1034:   Input Parameters:
    1035: + ds - The PetscDS object
    1036: - f  - The field number

    1038:   Output Parameter:
    1039: . k  - The highest derivative we need to tabulate

    1041:   Level: developer

    1043: .seealso: PetscDSSetJetDegree(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    1044: @*/
    1045: PetscErrorCode PetscDSGetJetDegree(PetscDS ds, PetscInt f, PetscInt *k)
    1046: {
    1050:   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
    1051:   *k = ds->jetDegree[f];
    1052:   return(0);
    1053: }

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

    1058:   Not collective

    1060:   Input Parameters:
    1061: + ds - The PetscDS object
    1062: . f  - The field number
    1063: - k  - The highest derivative we need to tabulate

    1065:   Level: developer

    1067: .seealso: PetscDSGetJetDegree(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    1068: @*/
    1069: PetscErrorCode PetscDSSetJetDegree(PetscDS ds, PetscInt f, PetscInt k)
    1070: {
    1073:   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
    1074:   ds->jetDegree[f] = k;
    1075:   return(0);
    1076: }

    1078: PetscErrorCode PetscDSGetObjective(PetscDS ds, PetscInt f,
    1079:                                    void (**obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1080:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1081:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1082:                                                 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]))
    1083: {
    1084:   PetscPointFunc *tmp;
    1085:   PetscInt        n;
    1086:   PetscErrorCode  ierr;

    1091:   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
    1092:   PetscWeakFormGetObjective(ds->wf, NULL, 0, f, &n, &tmp);
    1093:   *obj = tmp ? tmp[0] : NULL;
    1094:   return(0);
    1095: }

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

    1108:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    1109:   PetscWeakFormSetIndexObjective(ds->wf, NULL, 0, f, 0, obj);
    1110:   return(0);
    1111: }

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

    1116:   Not collective

    1118:   Input Parameters:
    1119: + ds - The PetscDS
    1120: - f  - The test field number

    1122:   Output Parameters:
    1123: + f0 - integrand for the test function term
    1124: - f1 - integrand for the test function gradient term

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

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

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

    1132: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1133: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1134: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1135: $    PetscReal t, const PetscReal x[], PetscScalar f0[])

    1137: + dim - the spatial dimension
    1138: . Nf - the number of fields
    1139: . uOff - the offset into u[] and u_t[] for each field
    1140: . uOff_x - the offset into u_x[] for each field
    1141: . u - each field evaluated at the current point
    1142: . u_t - the time derivative of each field evaluated at the current point
    1143: . u_x - the gradient of each field evaluated at the current point
    1144: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1145: . aOff_x - the offset into a_x[] for each auxiliary field
    1146: . a - each auxiliary field evaluated at the current point
    1147: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1148: . a_x - the gradient of auxiliary each field evaluated at the current point
    1149: . t - current time
    1150: . x - coordinates of the current point
    1151: . numConstants - number of constant parameters
    1152: . constants - constant parameters
    1153: - f0 - output values at the current point

    1155:   Level: intermediate

    1157: .seealso: PetscDSSetResidual()
    1158: @*/
    1159: PetscErrorCode PetscDSGetResidual(PetscDS ds, PetscInt f,
    1160:                                   void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1161:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1162:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1163:                                               PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
    1164:                                   void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1165:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1166:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1167:                                               PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
    1168: {
    1169:   PetscPointFunc *tmp0, *tmp1;
    1170:   PetscInt        n0, n1;
    1171:   PetscErrorCode  ierr;

    1175:   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
    1176:   PetscWeakFormGetResidual(ds->wf, NULL, 0, f, &n0, &tmp0, &n1, &tmp1);
    1177:   *f0  = tmp0 ? tmp0[0] : NULL;
    1178:   *f1  = tmp1 ? tmp1[0] : NULL;
    1179:   return(0);
    1180: }

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

    1185:   Not collective

    1187:   Input Parameters:
    1188: + ds - The PetscDS
    1189: . f  - The test field number
    1190: . f0 - integrand for the test function term
    1191: - f1 - integrand for the test function gradient term

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

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

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

    1199: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1200: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1201: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1202: $    PetscReal t, const PetscReal x[], PetscScalar f0[])

    1204: + dim - the spatial dimension
    1205: . Nf - the number of fields
    1206: . uOff - the offset into u[] and u_t[] for each field
    1207: . uOff_x - the offset into u_x[] for each field
    1208: . u - each field evaluated at the current point
    1209: . u_t - the time derivative of each field evaluated at the current point
    1210: . u_x - the gradient of each field evaluated at the current point
    1211: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1212: . aOff_x - the offset into a_x[] for each auxiliary field
    1213: . a - each auxiliary field evaluated at the current point
    1214: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1215: . a_x - the gradient of auxiliary each field evaluated at the current point
    1216: . t - current time
    1217: . x - coordinates of the current point
    1218: . numConstants - number of constant parameters
    1219: . constants - constant parameters
    1220: - f0 - output values at the current point

    1222:   Level: intermediate

    1224: .seealso: PetscDSGetResidual()
    1225: @*/
    1226: PetscErrorCode PetscDSSetResidual(PetscDS ds, PetscInt f,
    1227:                                   void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1228:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1229:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1230:                                              PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
    1231:                                   void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1232:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1233:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1234:                                              PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
    1235: {

    1242:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    1243:   PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 0, f0, 0, f1);
    1244:   return(0);
    1245: }

    1247: /*@C
    1248:   PetscDSHasJacobian - Signals that Jacobian functions have been set

    1250:   Not collective

    1252:   Input Parameter:
    1253: . prob - The PetscDS

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

    1258:   Level: intermediate

    1260: .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
    1261: @*/
    1262: PetscErrorCode PetscDSHasJacobian(PetscDS ds, PetscBool *hasJac)
    1263: {

    1268:   PetscWeakFormHasJacobian(ds->wf, hasJac);
    1269:   return(0);
    1270: }

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

    1275:   Not collective

    1277:   Input Parameters:
    1278: + ds - The PetscDS
    1279: . f  - The test field number
    1280: - g  - The field number

    1282:   Output Parameters:
    1283: + g0 - integrand for the test and basis function term
    1284: . g1 - integrand for the test function and basis function gradient term
    1285: . g2 - integrand for the test function gradient and basis function term
    1286: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

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

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

    1318:   Level: intermediate

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

    1346:   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
    1347:   if ((g < 0) || (g >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, ds->Nf);
    1348:   PetscWeakFormGetJacobian(ds->wf, NULL, 0, f, g, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);
    1349:   *g0  = tmp0 ? tmp0[0] : NULL;
    1350:   *g1  = tmp1 ? tmp1[0] : NULL;
    1351:   *g2  = tmp2 ? tmp2[0] : NULL;
    1352:   *g3  = tmp3 ? tmp3[0] : NULL;
    1353:   return(0);
    1354: }

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

    1359:   Not collective

    1361:   Input Parameters:
    1362: + ds - The PetscDS
    1363: . f  - The test field number
    1364: . g  - The field number
    1365: . g0 - integrand for the test and basis function term
    1366: . g1 - integrand for the test function and basis function gradient term
    1367: . g2 - integrand for the test function gradient and basis function term
    1368: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

    1376: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1377: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1378: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1379: $    PetscReal t, const PetscReal x[], PetscScalar g0[])

    1381: + dim - the spatial dimension
    1382: . Nf - the number of fields
    1383: . uOff - the offset into u[] and u_t[] for each field
    1384: . uOff_x - the offset into u_x[] for each field
    1385: . u - each field evaluated at the current point
    1386: . u_t - the time derivative of each field evaluated at the current point
    1387: . u_x - the gradient of each field evaluated at the current point
    1388: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1389: . aOff_x - the offset into a_x[] for each auxiliary field
    1390: . a - each auxiliary field evaluated at the current point
    1391: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1392: . a_x - the gradient of auxiliary each field evaluated at the current point
    1393: . t - current time
    1394: . u_tShift - the multiplier a for dF/dU_t
    1395: . x - coordinates of the current point
    1396: . numConstants - number of constant parameters
    1397: . constants - constant parameters
    1398: - g0 - output values at the current point

    1400:   Level: intermediate

    1402: .seealso: PetscDSGetJacobian()
    1403: @*/
    1404: PetscErrorCode PetscDSSetJacobian(PetscDS ds, PetscInt f, PetscInt g,
    1405:                                   void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1406:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1407:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1408:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    1409:                                   void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1410:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1411:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1412:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    1413:                                   void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1414:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1415:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1416:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    1417:                                   void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1418:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1419:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1420:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    1421: {

    1430:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    1431:   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
    1432:   PetscWeakFormSetIndexJacobian(ds->wf, NULL, 0, f, g, 0, g0, 0, g1, 0, g2, 0, g3);
    1433:   return(0);
    1434: }

    1436: /*@C
    1437:   PetscDSUseJacobianPreconditioner - Whether to construct a Jacobian preconditioner

    1439:   Not collective

    1441:   Input Parameters:
    1442: + prob - The PetscDS
    1443: - useJacPre - flag that enables construction of a Jacobian preconditioner

    1445:   Level: intermediate

    1447: .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
    1448: @*/
    1449: PetscErrorCode PetscDSUseJacobianPreconditioner(PetscDS prob, PetscBool useJacPre)
    1450: {
    1453:   prob->useJacPre = useJacPre;
    1454:   return(0);
    1455: }

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

    1460:   Not collective

    1462:   Input Parameter:
    1463: . prob - The PetscDS

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

    1468:   Level: intermediate

    1470: .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
    1471: @*/
    1472: PetscErrorCode PetscDSHasJacobianPreconditioner(PetscDS ds, PetscBool *hasJacPre)
    1473: {

    1478:   *hasJacPre = PETSC_FALSE;
    1479:   if (!ds->useJacPre) return(0);
    1480:   PetscWeakFormHasJacobianPreconditioner(ds->wf, hasJacPre);
    1481:   return(0);
    1482: }

    1484: /*@C
    1485:   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.

    1487:   Not collective

    1489:   Input Parameters:
    1490: + ds - The PetscDS
    1491: . f  - The test field number
    1492: - g  - The field number

    1494:   Output Parameters:
    1495: + g0 - integrand for the test and basis function term
    1496: . g1 - integrand for the test function and basis function gradient term
    1497: . g2 - integrand for the test function gradient and basis function term
    1498: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

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

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

    1530:   Level: intermediate

    1532: .seealso: PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
    1533: @*/
    1534: PetscErrorCode PetscDSGetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g,
    1535:                                   void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1536:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1537:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1538:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    1539:                                   void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1540:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1541:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1542:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    1543:                                   void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1544:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1545:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1546:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    1547:                                   void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1548:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1549:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1550:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    1551: {
    1552:   PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
    1553:   PetscInt       n0, n1, n2, n3;

    1558:   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
    1559:   if ((g < 0) || (g >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, ds->Nf);
    1560:   PetscWeakFormGetJacobianPreconditioner(ds->wf, NULL, 0, f, g, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);
    1561:   *g0  = tmp0 ? tmp0[0] : NULL;
    1562:   *g1  = tmp1 ? tmp1[0] : NULL;
    1563:   *g2  = tmp2 ? tmp2[0] : NULL;
    1564:   *g3  = tmp3 ? tmp3[0] : NULL;
    1565:   return(0);
    1566: }

    1568: /*@C
    1569:   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.

    1571:   Not collective

    1573:   Input Parameters:
    1574: + ds - The PetscDS
    1575: . f  - The test field number
    1576: . g  - The field number
    1577: . g0 - integrand for the test and basis function term
    1578: . g1 - integrand for the test function and basis function gradient term
    1579: . g2 - integrand for the test function gradient and basis function term
    1580: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

    1588: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1589: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1590: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1591: $    PetscReal t, const PetscReal x[], PetscScalar g0[])

    1593: + dim - the spatial dimension
    1594: . Nf - the number of fields
    1595: . uOff - the offset into u[] and u_t[] for each field
    1596: . uOff_x - the offset into u_x[] for each field
    1597: . u - each field evaluated at the current point
    1598: . u_t - the time derivative of each field evaluated at the current point
    1599: . u_x - the gradient of each field evaluated at the current point
    1600: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1601: . aOff_x - the offset into a_x[] for each auxiliary field
    1602: . a - each auxiliary field evaluated at the current point
    1603: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1604: . a_x - the gradient of auxiliary each field evaluated at the current point
    1605: . t - current time
    1606: . u_tShift - the multiplier a for dF/dU_t
    1607: . x - coordinates of the current point
    1608: . numConstants - number of constant parameters
    1609: . constants - constant parameters
    1610: - g0 - output values at the current point

    1612:   Level: intermediate

    1614: .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobian()
    1615: @*/
    1616: PetscErrorCode PetscDSSetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g,
    1617:                                   void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1618:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1619:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1620:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    1621:                                   void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1622:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1623:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1624:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    1625:                                   void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1626:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1627:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1628:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    1629:                                   void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1630:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1631:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1632:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    1633: {

    1642:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    1643:   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
    1644:   PetscWeakFormSetIndexJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, g0, 0, g1, 0, g2, 0, g3);
    1645:   return(0);
    1646: }

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

    1651:   Not collective

    1653:   Input Parameter:
    1654: . ds - The PetscDS

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

    1659:   Level: intermediate

    1661: .seealso: PetscDSGetDynamicJacobian(), PetscDSSetDynamicJacobian(), PetscDSGetJacobian()
    1662: @*/
    1663: PetscErrorCode PetscDSHasDynamicJacobian(PetscDS ds, PetscBool *hasDynJac)
    1664: {

    1669:   PetscWeakFormHasDynamicJacobian(ds->wf, hasDynJac);
    1670:   return(0);
    1671: }

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

    1676:   Not collective

    1678:   Input Parameters:
    1679: + ds - The PetscDS
    1680: . f  - The test field number
    1681: - g  - The field number

    1683:   Output Parameters:
    1684: + g0 - integrand for the test and basis function term
    1685: . g1 - integrand for the test function and basis function gradient term
    1686: . g2 - integrand for the test function gradient and basis function term
    1687: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

    1695: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1696: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1697: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1698: $    PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])

    1700: + dim - the spatial dimension
    1701: . Nf - the number of fields
    1702: . uOff - the offset into u[] and u_t[] for each field
    1703: . uOff_x - the offset into u_x[] for each field
    1704: . u - each field evaluated at the current point
    1705: . u_t - the time derivative of each field evaluated at the current point
    1706: . u_x - the gradient of each field evaluated at the current point
    1707: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1708: . aOff_x - the offset into a_x[] for each auxiliary field
    1709: . a - each auxiliary field evaluated at the current point
    1710: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1711: . a_x - the gradient of auxiliary each field evaluated at the current point
    1712: . t - current time
    1713: . u_tShift - the multiplier a for dF/dU_t
    1714: . x - coordinates of the current point
    1715: . numConstants - number of constant parameters
    1716: . constants - constant parameters
    1717: - g0 - output values at the current point

    1719:   Level: intermediate

    1721: .seealso: PetscDSSetJacobian()
    1722: @*/
    1723: PetscErrorCode PetscDSGetDynamicJacobian(PetscDS ds, PetscInt f, PetscInt g,
    1724:                                          void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1725:                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1726:                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1727:                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    1728:                                          void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1729:                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1730:                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1731:                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    1732:                                          void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1733:                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1734:                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1735:                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    1736:                                          void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1737:                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1738:                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1739:                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    1740: {
    1741:   PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
    1742:   PetscInt       n0, n1, n2, n3;

    1747:   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
    1748:   if ((g < 0) || (g >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, ds->Nf);
    1749:   PetscWeakFormGetDynamicJacobian(ds->wf, NULL, 0, f, g, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);
    1750:   *g0  = tmp0 ? tmp0[0] : NULL;
    1751:   *g1  = tmp1 ? tmp1[0] : NULL;
    1752:   *g2  = tmp2 ? tmp2[0] : NULL;
    1753:   *g3  = tmp3 ? tmp3[0] : NULL;
    1754:   return(0);
    1755: }

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

    1760:   Not collective

    1762:   Input Parameters:
    1763: + ds - The PetscDS
    1764: . f  - The test field number
    1765: . g  - The field number
    1766: . g0 - integrand for the test and basis function term
    1767: . g1 - integrand for the test function and basis function gradient term
    1768: . g2 - integrand for the test function gradient and basis function term
    1769: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

    1777: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1778: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1779: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1780: $    PetscReal t, const PetscReal x[], PetscScalar g0[])

    1782: + dim - the spatial dimension
    1783: . Nf - the number of fields
    1784: . uOff - the offset into u[] and u_t[] for each field
    1785: . uOff_x - the offset into u_x[] for each field
    1786: . u - each field evaluated at the current point
    1787: . u_t - the time derivative of each field evaluated at the current point
    1788: . u_x - the gradient of each field evaluated at the current point
    1789: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1790: . aOff_x - the offset into a_x[] for each auxiliary field
    1791: . a - each auxiliary field evaluated at the current point
    1792: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1793: . a_x - the gradient of auxiliary each field evaluated at the current point
    1794: . t - current time
    1795: . u_tShift - the multiplier a for dF/dU_t
    1796: . x - coordinates of the current point
    1797: . numConstants - number of constant parameters
    1798: . constants - constant parameters
    1799: - g0 - output values at the current point

    1801:   Level: intermediate

    1803: .seealso: PetscDSGetJacobian()
    1804: @*/
    1805: PetscErrorCode PetscDSSetDynamicJacobian(PetscDS ds, PetscInt f, PetscInt g,
    1806:                                          void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1807:                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1808:                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1809:                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    1810:                                          void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1811:                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1812:                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1813:                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    1814:                                          void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1815:                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1816:                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1817:                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    1818:                                          void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1819:                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1820:                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1821:                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    1822: {

    1831:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    1832:   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
    1833:   PetscWeakFormSetIndexDynamicJacobian(ds->wf, NULL, 0, f, g, 0, g0, 0, g1, 0, g2, 0, g3);
    1834:   return(0);
    1835: }

    1837: /*@C
    1838:   PetscDSGetRiemannSolver - Returns the Riemann solver for the given field

    1840:   Not collective

    1842:   Input Arguments:
    1843: + ds - The PetscDS object
    1844: - f  - The field number

    1846:   Output Argument:
    1847: . r    - Riemann solver

    1849:   Calling sequence for r:

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

    1853: + dim  - The spatial dimension
    1854: . Nf   - The number of fields
    1855: . x    - The coordinates at a point on the interface
    1856: . n    - The normal vector to the interface
    1857: . uL   - The state vector to the left of the interface
    1858: . uR   - The state vector to the right of the interface
    1859: . flux - output array of flux through the interface
    1860: . numConstants - number of constant parameters
    1861: . constants - constant parameters
    1862: - ctx  - optional user context

    1864:   Level: intermediate

    1866: .seealso: PetscDSSetRiemannSolver()
    1867: @*/
    1868: PetscErrorCode PetscDSGetRiemannSolver(PetscDS ds, PetscInt f,
    1869:                                        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))
    1870: {
    1871:   PetscRiemannFunc *tmp;
    1872:   PetscInt          n;
    1873:   PetscErrorCode    ierr;

    1878:   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
    1879:   PetscWeakFormGetRiemannSolver(ds->wf, NULL, 0, f, &n, &tmp);
    1880:   *r   = tmp ? tmp[0] : NULL;
    1881:   return(0);
    1882: }

    1884: /*@C
    1885:   PetscDSSetRiemannSolver - Sets the Riemann solver for the given field

    1887:   Not collective

    1889:   Input Arguments:
    1890: + ds - The PetscDS object
    1891: . f  - The field number
    1892: - r  - Riemann solver

    1894:   Calling sequence for r:

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

    1898: + dim  - The spatial dimension
    1899: . Nf   - The number of fields
    1900: . x    - The coordinates at a point on the interface
    1901: . n    - The normal vector to the interface
    1902: . uL   - The state vector to the left of the interface
    1903: . uR   - The state vector to the right of the interface
    1904: . flux - output array of flux through the interface
    1905: . numConstants - number of constant parameters
    1906: . constants - constant parameters
    1907: - ctx  - optional user context

    1909:   Level: intermediate

    1911: .seealso: PetscDSGetRiemannSolver()
    1912: @*/
    1913: PetscErrorCode PetscDSSetRiemannSolver(PetscDS ds, PetscInt f,
    1914:                                        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))
    1915: {

    1921:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    1922:   PetscWeakFormSetIndexRiemannSolver(ds->wf, NULL, 0, f, 0, r);
    1923:   return(0);
    1924: }

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

    1929:   Not collective

    1931:   Input Parameters:
    1932: + ds - The PetscDS
    1933: - f  - The field number

    1935:   Output Parameters:
    1936: . update - update function

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

    1940: $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1941: $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1942: $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1943: $        PetscReal t, const PetscReal x[], PetscScalar uNew[])

    1945: + dim - the spatial dimension
    1946: . Nf - the number of fields
    1947: . uOff - the offset into u[] and u_t[] for each field
    1948: . uOff_x - the offset into u_x[] for each field
    1949: . u - each field evaluated at the current point
    1950: . u_t - the time derivative of each field evaluated at the current point
    1951: . u_x - the gradient of each field evaluated at the current point
    1952: . aOff - the offset into a[] and a_t[] for each auxiliary field
    1953: . aOff_x - the offset into a_x[] for each auxiliary field
    1954: . a - each auxiliary field evaluated at the current point
    1955: . a_t - the time derivative of each auxiliary field evaluated at the current point
    1956: . a_x - the gradient of auxiliary each field evaluated at the current point
    1957: . t - current time
    1958: . x - coordinates of the current point
    1959: - uNew - new value for field at the current point

    1961:   Level: intermediate

    1963: .seealso: PetscDSSetUpdate(), PetscDSSetResidual()
    1964: @*/
    1965: PetscErrorCode PetscDSGetUpdate(PetscDS ds, PetscInt f,
    1966:                                   void (**update)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1967:                                                   const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1968:                                                   const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1969:                                                   PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[]))
    1970: {
    1973:   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
    1975:   return(0);
    1976: }

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

    1981:   Not collective

    1983:   Input Parameters:
    1984: + ds     - The PetscDS
    1985: . f      - The field number
    1986: - update - update function

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

    1990: $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    1991: $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    1992: $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    1993: $        PetscReal t, const PetscReal x[], PetscScalar uNew[])

    1995: + dim - the spatial dimension
    1996: . Nf - the number of fields
    1997: . uOff - the offset into u[] and u_t[] for each field
    1998: . uOff_x - the offset into u_x[] for each field
    1999: . u - each field evaluated at the current point
    2000: . u_t - the time derivative of each field evaluated at the current point
    2001: . u_x - the gradient of each field evaluated at the current point
    2002: . aOff - the offset into a[] and a_t[] for each auxiliary field
    2003: . aOff_x - the offset into a_x[] for each auxiliary field
    2004: . a - each auxiliary field evaluated at the current point
    2005: . a_t - the time derivative of each auxiliary field evaluated at the current point
    2006: . a_x - the gradient of auxiliary each field evaluated at the current point
    2007: . t - current time
    2008: . x - coordinates of the current point
    2009: - uNew - new field values at the current point

    2011:   Level: intermediate

    2013: .seealso: PetscDSGetResidual()
    2014: @*/
    2015: PetscErrorCode PetscDSSetUpdate(PetscDS ds, PetscInt f,
    2016:                                 void (*update)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2017:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2018:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2019:                                                PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[]))
    2020: {

    2026:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    2027:   PetscDSEnlarge_Static(ds, f+1);
    2028:   ds->update[f] = update;
    2029:   return(0);
    2030: }

    2032: PetscErrorCode PetscDSGetContext(PetscDS ds, PetscInt f, void **ctx)
    2033: {
    2036:   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
    2038:   *ctx = ds->ctx[f];
    2039:   return(0);
    2040: }

    2042: PetscErrorCode PetscDSSetContext(PetscDS ds, PetscInt f, void *ctx)
    2043: {

    2048:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    2049:   PetscDSEnlarge_Static(ds, f+1);
    2050:   ds->ctx[f] = ctx;
    2051:   return(0);
    2052: }

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

    2057:   Not collective

    2059:   Input Parameters:
    2060: + ds - The PetscDS
    2061: - f  - The test field number

    2063:   Output Parameters:
    2064: + f0 - boundary integrand for the test function term
    2065: - f1 - boundary integrand for the test function gradient term

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

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

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

    2073: $ f0(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[], const PetscReal n[], PetscScalar f0[])

    2078: + dim - the spatial dimension
    2079: . Nf - the number of fields
    2080: . uOff - the offset into u[] and u_t[] for each field
    2081: . uOff_x - the offset into u_x[] for each field
    2082: . u - each field evaluated at the current point
    2083: . u_t - the time derivative of each field evaluated at the current point
    2084: . u_x - the gradient of each field evaluated at the current point
    2085: . aOff - the offset into a[] and a_t[] for each auxiliary field
    2086: . aOff_x - the offset into a_x[] for each auxiliary field
    2087: . a - each auxiliary field evaluated at the current point
    2088: . a_t - the time derivative of each auxiliary field evaluated at the current point
    2089: . a_x - the gradient of auxiliary each field evaluated at the current point
    2090: . t - current time
    2091: . x - coordinates of the current point
    2092: . n - unit normal at the current point
    2093: . numConstants - number of constant parameters
    2094: . constants - constant parameters
    2095: - f0 - output values at the current point

    2097:   Level: intermediate

    2099: .seealso: PetscDSSetBdResidual()
    2100: @*/
    2101: PetscErrorCode PetscDSGetBdResidual(PetscDS ds, PetscInt f,
    2102:                                     void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2103:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2104:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2105:                                                 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
    2106:                                     void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2107:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2108:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2109:                                                 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
    2110: {
    2111:   PetscBdPointFunc *tmp0, *tmp1;
    2112:   PetscInt          n0, n1;
    2113:   PetscErrorCode    ierr;

    2117:   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
    2118:   PetscWeakFormGetBdResidual(ds->wf, NULL, 0, f, &n0, &tmp0, &n1, &tmp1);
    2119:   *f0  = tmp0 ? tmp0[0] : NULL;
    2120:   *f1  = tmp1 ? tmp1[0] : NULL;
    2121:   return(0);
    2122: }

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

    2127:   Not collective

    2129:   Input Parameters:
    2130: + ds - The PetscDS
    2131: . f  - The test field number
    2132: . f0 - boundary integrand for the test function term
    2133: - f1 - boundary integrand for the test function gradient term

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

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

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

    2141: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2142: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2143: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2144: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])

    2146: + dim - the spatial dimension
    2147: . Nf - the number of fields
    2148: . uOff - the offset into u[] and u_t[] for each field
    2149: . uOff_x - the offset into u_x[] for each field
    2150: . u - each field evaluated at the current point
    2151: . u_t - the time derivative of each field evaluated at the current point
    2152: . u_x - the gradient of each field evaluated at the current point
    2153: . aOff - the offset into a[] and a_t[] for each auxiliary field
    2154: . aOff_x - the offset into a_x[] for each auxiliary field
    2155: . a - each auxiliary field evaluated at the current point
    2156: . a_t - the time derivative of each auxiliary field evaluated at the current point
    2157: . a_x - the gradient of auxiliary each field evaluated at the current point
    2158: . t - current time
    2159: . x - coordinates of the current point
    2160: . n - unit normal at the current point
    2161: . numConstants - number of constant parameters
    2162: . constants - constant parameters
    2163: - f0 - output values at the current point

    2165:   Level: intermediate

    2167: .seealso: PetscDSGetBdResidual()
    2168: @*/
    2169: PetscErrorCode PetscDSSetBdResidual(PetscDS ds, PetscInt f,
    2170:                                     void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2171:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2172:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2173:                                                PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
    2174:                                     void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2175:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2176:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2177:                                                PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
    2178: {

    2183:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    2184:   PetscWeakFormSetIndexBdResidual(ds->wf, NULL, 0, f, 0, f0, 0, f1);
    2185:   return(0);
    2186: }

    2188: /*@
    2189:   PetscDSHasBdJacobian - Signals that boundary Jacobian functions have been set

    2191:   Not collective

    2193:   Input Parameter:
    2194: . ds - The PetscDS

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

    2199:   Level: intermediate

    2201: .seealso: PetscDSHasJacobian(), PetscDSSetBdJacobian(), PetscDSGetBdJacobian()
    2202: @*/
    2203: PetscErrorCode PetscDSHasBdJacobian(PetscDS ds, PetscBool *hasBdJac)
    2204: {

    2210:   PetscWeakFormHasBdJacobian(ds->wf, hasBdJac);
    2211:   return(0);
    2212: }

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

    2217:   Not collective

    2219:   Input Parameters:
    2220: + ds - The PetscDS
    2221: . f  - The test field number
    2222: - g  - The field number

    2224:   Output Parameters:
    2225: + g0 - integrand for the test and basis function term
    2226: . g1 - integrand for the test function and basis function gradient term
    2227: . g2 - integrand for the test function gradient and basis function term
    2228: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

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

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

    2261:   Level: intermediate

    2263: .seealso: PetscDSSetBdJacobian()
    2264: @*/
    2265: PetscErrorCode PetscDSGetBdJacobian(PetscDS ds, PetscInt f, PetscInt g,
    2266:                                     void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2267:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2268:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2269:                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    2270:                                     void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2271:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2272:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2273:                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    2274:                                     void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2275:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2276:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2277:                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    2278:                                     void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2279:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2280:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2281:                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    2282: {
    2283:   PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3;
    2284:   PetscInt         n0, n1, n2, n3;
    2285:   PetscErrorCode   ierr;

    2289:   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
    2290:   if ((g < 0) || (g >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, ds->Nf);
    2291:   PetscWeakFormGetBdJacobian(ds->wf, NULL, 0, f, g, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);
    2292:   *g0  = tmp0 ? tmp0[0] : NULL;
    2293:   *g1  = tmp1 ? tmp1[0] : NULL;
    2294:   *g2  = tmp2 ? tmp2[0] : NULL;
    2295:   *g3  = tmp3 ? tmp3[0] : NULL;
    2296:   return(0);
    2297: }

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

    2302:   Not collective

    2304:   Input Parameters:
    2305: + ds - The PetscDS
    2306: . f  - The test field number
    2307: . g  - The field number
    2308: . g0 - integrand for the test and basis function term
    2309: . g1 - integrand for the test function and basis function gradient term
    2310: . g2 - integrand for the test function gradient and basis function term
    2311: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

    2319: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2320: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2321: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2322: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[])

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

    2344:   Level: intermediate

    2346: .seealso: PetscDSGetBdJacobian()
    2347: @*/
    2348: PetscErrorCode PetscDSSetBdJacobian(PetscDS ds, PetscInt f, PetscInt g,
    2349:                                     void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2350:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2351:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2352:                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    2353:                                     void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2354:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2355:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2356:                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    2357:                                     void (*g2)(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 g2[]),
    2361:                                     void (*g3)(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 g3[]))
    2365: {

    2374:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    2375:   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
    2376:   PetscWeakFormSetIndexBdJacobian(ds->wf, NULL, 0, f, g, 0, g0, 0, g1, 0, g2, 0, g3);
    2377:   return(0);
    2378: }

    2380: /*@
    2381:   PetscDSHasBdJacobianPreconditioner - Signals that boundary Jacobian preconditioner functions have been set

    2383:   Not collective

    2385:   Input Parameter:
    2386: . ds - The PetscDS

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

    2391:   Level: intermediate

    2393: .seealso: PetscDSHasJacobian(), PetscDSSetBdJacobian(), PetscDSGetBdJacobian()
    2394: @*/
    2395: PetscErrorCode PetscDSHasBdJacobianPreconditioner(PetscDS ds, PetscBool *hasBdJacPre)
    2396: {

    2402:   PetscWeakFormHasBdJacobianPreconditioner(ds->wf, hasBdJacPre);
    2403:   return(0);
    2404: }

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

    2409:   Not collective

    2411:   Input Parameters:
    2412: + ds - The PetscDS
    2413: . f  - The test field number
    2414: - g  - The field number

    2416:   Output Parameters:
    2417: + g0 - integrand for the test and basis function term
    2418: . g1 - integrand for the test function and basis function gradient term
    2419: . g2 - integrand for the test function gradient and basis function term
    2420: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

    2428: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2429: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2430: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2431: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])

    2433: + dim - the spatial dimension
    2434: . Nf - the number of fields
    2435: . NfAux - the number of auxiliary fields
    2436: . uOff - the offset into u[] and u_t[] for each field
    2437: . uOff_x - the offset into u_x[] for each field
    2438: . u - each field evaluated at the current point
    2439: . u_t - the time derivative of each field evaluated at the current point
    2440: . u_x - the gradient of each field evaluated at the current point
    2441: . aOff - the offset into a[] and a_t[] for each auxiliary field
    2442: . aOff_x - the offset into a_x[] for each auxiliary field
    2443: . a - each auxiliary field evaluated at the current point
    2444: . a_t - the time derivative of each auxiliary field evaluated at the current point
    2445: . a_x - the gradient of auxiliary each field evaluated at the current point
    2446: . t - current time
    2447: . u_tShift - the multiplier a for dF/dU_t
    2448: . x - coordinates of the current point
    2449: . n - normal at the current point
    2450: . numConstants - number of constant parameters
    2451: . constants - constant parameters
    2452: - g0 - output values at the current point

    2454:   This is not yet available in Fortran.

    2456:   Level: intermediate

    2458: .seealso: PetscDSSetBdJacobianPreconditioner()
    2459: @*/
    2460: PetscErrorCode PetscDSGetBdJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g,
    2461:                                                   void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2462:                                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2463:                                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2464:                                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
    2465:                                                   void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2466:                                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2467:                                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2468:                                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
    2469:                                                   void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2470:                                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2471:                                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2472:                                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
    2473:                                                   void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    2474:                                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    2475:                                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    2476:                                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
    2477: {
    2478:   PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3;
    2479:   PetscInt         n0, n1, n2, n3;
    2480:   PetscErrorCode   ierr;

    2484:   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
    2485:   if ((g < 0) || (g >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, ds->Nf);
    2486:   PetscWeakFormGetBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);
    2487:   *g0  = tmp0 ? tmp0[0] : NULL;
    2488:   *g1  = tmp1 ? tmp1[0] : NULL;
    2489:   *g2  = tmp2 ? tmp2[0] : NULL;
    2490:   *g3  = tmp3 ? tmp3[0] : NULL;
    2491:   return(0);
    2492: }

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

    2497:   Not collective

    2499:   Input Parameters:
    2500: + ds - The PetscDS
    2501: . f  - The test field number
    2502: . g  - The field number
    2503: . g0 - integrand for the test and basis function term
    2504: . g1 - integrand for the test function and basis function gradient term
    2505: . g2 - integrand for the test function gradient and basis function term
    2506: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

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

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

    2540:   This is not yet available in Fortran.

    2542:   Level: intermediate

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

    2572:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    2573:   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
    2574:   PetscWeakFormSetIndexBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, g0, 0, g1, 0, g2, 0, g3);
    2575:   return(0);
    2576: }

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

    2581:   Not collective

    2583:   Input Parameters:
    2584: + prob - The PetscDS
    2585: - f    - The test field number

    2587:   Output Parameter:
    2588: + exactSol - exact solution for the test field
    2589: - exactCtx - exact solution context

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

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

    2595: + dim - the spatial dimension
    2596: . t - current time
    2597: . x - coordinates of the current point
    2598: . Nc - the number of field components
    2599: . u - the solution field evaluated at the current point
    2600: - ctx - a user context

    2602:   Level: intermediate

    2604: .seealso: PetscDSSetExactSolution(), PetscDSGetExactSolutionTimeDerivative()
    2605: @*/
    2606: PetscErrorCode PetscDSGetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx)
    2607: {
    2610:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    2613:   return(0);
    2614: }

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

    2619:   Not collective

    2621:   Input Parameters:
    2622: + prob - The PetscDS
    2623: . f    - The test field number
    2624: . sol  - solution function for the test fields
    2625: - ctx  - solution context or NULL

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

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

    2631: + dim - the spatial dimension
    2632: . t - current time
    2633: . x - coordinates of the current point
    2634: . Nc - the number of field components
    2635: . u - the solution field evaluated at the current point
    2636: - ctx - a user context

    2638:   Level: intermediate

    2640: .seealso: PetscDSGetExactSolution()
    2641: @*/
    2642: PetscErrorCode PetscDSSetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx)
    2643: {

    2648:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    2649:   PetscDSEnlarge_Static(prob, f+1);
    2652:   return(0);
    2653: }

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

    2658:   Not collective

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

    2664:   Output Parameter:
    2665: + exactSol - time derivative of the exact solution for the test field
    2666: - exactCtx - time derivative of the exact solution context

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

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

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

    2679:   Level: intermediate

    2681: .seealso: PetscDSSetExactSolutionTimeDerivative(), PetscDSGetExactSolution()
    2682: @*/
    2683: PetscErrorCode PetscDSGetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx)
    2684: {
    2687:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    2690:   return(0);
    2691: }

    2693: /*@C
    2694:   PetscDSSetExactSolutionTimeDerivative - Set the pointwise time derivative of the 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  - time derivative of the solution function for the test fields
    2702: - ctx  - time derivative of the 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: PetscDSGetExactSolutionTimeDerivative(), PetscDSSetExactSolution()
    2718: @*/
    2719: PetscErrorCode PetscDSSetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx)
    2720: {

    2725:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
    2726:   PetscDSEnlarge_Static(prob, f+1);
    2729:   return(0);
    2730: }

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

    2735:   Not collective

    2737:   Input Parameter:
    2738: . prob - The PetscDS object

    2740:   Output Parameters:
    2741: + numConstants - The number of constants
    2742: - constants    - The array of constants, NULL if there are none

    2744:   Level: intermediate

    2746: .seealso: PetscDSSetConstants(), PetscDSCreate()
    2747: @*/
    2748: PetscErrorCode PetscDSGetConstants(PetscDS prob, PetscInt *numConstants, const PetscScalar *constants[])
    2749: {
    2754:   return(0);
    2755: }

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

    2760:   Not collective

    2762:   Input Parameters:
    2763: + prob         - The PetscDS object
    2764: . numConstants - The number of constants
    2765: - constants    - The array of constants, NULL if there are none

    2767:   Level: intermediate

    2769: .seealso: PetscDSGetConstants(), PetscDSCreate()
    2770: @*/
    2771: PetscErrorCode PetscDSSetConstants(PetscDS prob, PetscInt numConstants, PetscScalar constants[])
    2772: {

    2777:   if (numConstants != prob->numConstants) {
    2778:     PetscFree(prob->constants);
    2779:     prob->numConstants = numConstants;
    2780:     if (prob->numConstants) {
    2781:       PetscMalloc1(prob->numConstants, &prob->constants);
    2782:     } else {
    2783:       prob->constants = NULL;
    2784:     }
    2785:   }
    2786:   if (prob->numConstants) {
    2788:     PetscArraycpy(prob->constants, constants, prob->numConstants);
    2789:   }
    2790:   return(0);
    2791: }

    2793: /*@
    2794:   PetscDSGetFieldIndex - Returns the index of the given field

    2796:   Not collective

    2798:   Input Parameters:
    2799: + prob - The PetscDS object
    2800: - disc - The discretization object

    2802:   Output Parameter:
    2803: . f - The field number

    2805:   Level: beginner

    2807: .seealso: PetscGetDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
    2808: @*/
    2809: PetscErrorCode PetscDSGetFieldIndex(PetscDS prob, PetscObject disc, PetscInt *f)
    2810: {
    2811:   PetscInt g;

    2816:   *f = -1;
    2817:   for (g = 0; g < prob->Nf; ++g) {if (disc == prob->disc[g]) break;}
    2818:   if (g == prob->Nf) SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Field not found in PetscDS.");
    2819:   *f = g;
    2820:   return(0);
    2821: }

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

    2826:   Not collective

    2828:   Input Parameters:
    2829: + prob - The PetscDS object
    2830: - f - The field number

    2832:   Output Parameter:
    2833: . size - The size

    2835:   Level: beginner

    2837: .seealso: PetscDSGetFieldOffset(), PetscDSGetNumFields(), PetscDSCreate()
    2838: @*/
    2839: PetscErrorCode PetscDSGetFieldSize(PetscDS prob, PetscInt f, PetscInt *size)
    2840: {

    2846:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    2847:   PetscDSSetUp(prob);
    2848:   *size = prob->Nb[f];
    2849:   return(0);
    2850: }

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

    2855:   Not collective

    2857:   Input Parameters:
    2858: + prob - The PetscDS object
    2859: - f - The field number

    2861:   Output Parameter:
    2862: . off - The offset

    2864:   Level: beginner

    2866: .seealso: PetscDSGetFieldSize(), PetscDSGetNumFields(), PetscDSCreate()
    2867: @*/
    2868: PetscErrorCode PetscDSGetFieldOffset(PetscDS prob, PetscInt f, PetscInt *off)
    2869: {
    2870:   PetscInt       size, g;

    2876:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    2877:   *off = 0;
    2878:   for (g = 0; g < f; ++g) {
    2879:     PetscDSGetFieldSize(prob, g, &size);
    2880:     *off += size;
    2881:   }
    2882:   return(0);
    2883: }

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

    2888:   Not collective

    2890:   Input Parameter:
    2891: . prob - The PetscDS object

    2893:   Output Parameter:
    2894: . dimensions - The number of dimensions

    2896:   Level: beginner

    2898: .seealso: PetscDSGetComponentOffsets(), PetscDSGetNumFields(), PetscDSCreate()
    2899: @*/
    2900: PetscErrorCode PetscDSGetDimensions(PetscDS prob, PetscInt *dimensions[])
    2901: {

    2906:   PetscDSSetUp(prob);
    2908:   *dimensions = prob->Nb;
    2909:   return(0);
    2910: }

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

    2915:   Not collective

    2917:   Input Parameter:
    2918: . prob - The PetscDS object

    2920:   Output Parameter:
    2921: . components - The number of components

    2923:   Level: beginner

    2925: .seealso: PetscDSGetComponentOffsets(), PetscDSGetNumFields(), PetscDSCreate()
    2926: @*/
    2927: PetscErrorCode PetscDSGetComponents(PetscDS prob, PetscInt *components[])
    2928: {

    2933:   PetscDSSetUp(prob);
    2935:   *components = prob->Nc;
    2936:   return(0);
    2937: }

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

    2942:   Not collective

    2944:   Input Parameters:
    2945: + prob - The PetscDS object
    2946: - f - The field number

    2948:   Output Parameter:
    2949: . off - The offset

    2951:   Level: beginner

    2953: .seealso: PetscDSGetNumFields(), PetscDSCreate()
    2954: @*/
    2955: PetscErrorCode PetscDSGetComponentOffset(PetscDS prob, PetscInt f, PetscInt *off)
    2956: {
    2960:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
    2961:   *off = prob->off[f];
    2962:   return(0);
    2963: }

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

    2968:   Not collective

    2970:   Input Parameter:
    2971: . prob - The PetscDS object

    2973:   Output Parameter:
    2974: . offsets - The offsets

    2976:   Level: beginner

    2978: .seealso: PetscDSGetNumFields(), PetscDSCreate()
    2979: @*/
    2980: PetscErrorCode PetscDSGetComponentOffsets(PetscDS prob, PetscInt *offsets[])
    2981: {
    2985:   *offsets = prob->off;
    2986:   return(0);
    2987: }

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

    2992:   Not collective

    2994:   Input Parameter:
    2995: . prob - The PetscDS object

    2997:   Output Parameter:
    2998: . offsets - The offsets

    3000:   Level: beginner

    3002: .seealso: PetscDSGetNumFields(), PetscDSCreate()
    3003: @*/
    3004: PetscErrorCode PetscDSGetComponentDerivativeOffsets(PetscDS prob, PetscInt *offsets[])
    3005: {
    3009:   *offsets = prob->offDer;
    3010:   return(0);
    3011: }

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

    3016:   Not collective

    3018:   Input Parameter:
    3019: . prob - The PetscDS object

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

    3024:   Level: intermediate

    3026: .seealso: PetscDSCreate()
    3027: @*/
    3028: PetscErrorCode PetscDSGetTabulation(PetscDS prob, PetscTabulation *T[])
    3029: {

    3035:   PetscDSSetUp(prob);
    3036:   *T = prob->T;
    3037:   return(0);
    3038: }

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

    3043:   Not collective

    3045:   Input Parameter:
    3046: . prob - The PetscDS object

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

    3051:   Level: intermediate

    3053: .seealso: PetscDSGetTabulation(), PetscDSCreate()
    3054: @*/
    3055: PetscErrorCode PetscDSGetFaceTabulation(PetscDS prob, PetscTabulation *Tf[])
    3056: {

    3062:   PetscDSSetUp(prob);
    3063:   *Tf = prob->Tf;
    3064:   return(0);
    3065: }

    3067: PetscErrorCode PetscDSGetEvaluationArrays(PetscDS prob, PetscScalar **u, PetscScalar **u_t, PetscScalar **u_x)
    3068: {

    3073:   PetscDSSetUp(prob);
    3077:   return(0);
    3078: }

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

    3086:   PetscDSSetUp(prob);
    3093:   return(0);
    3094: }

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

    3102:   PetscDSSetUp(prob);
    3108:   return(0);
    3109: }

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

    3114:   Collective on ds

    3116:   Input Parameters:
    3117: + ds          - The PetscDS object
    3118: . type        - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
    3119: . name        - The BC name
    3120: . labelname   - The label defining constrained points
    3121: . field       - The field to constrain
    3122: . numcomps    - The number of constrained field components (0 will constrain all fields)
    3123: . comps       - An array of constrained component numbers
    3124: . bcFunc      - A pointwise function giving boundary values
    3125: . bcFunc_t    - A pointwise function giving the time derviative of the boundary values, or NULL
    3126: . numids      - The number of DMLabel ids for constrained points
    3127: . ids         - An array of ids for constrained points
    3128: - ctx         - An optional user context for bcFunc

    3130:   Options Database Keys:
    3131: + -bc_<boundary name> <num> - Overrides the boundary ids
    3132: - -bc_<boundary name>_comp <num> - Overrides the boundary components

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

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

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

    3141: $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
    3142: $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
    3143: $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
    3144: $        PetscReal time, const PetscReal x[], PetscScalar bcval[])

    3146: + dim - the spatial dimension
    3147: . Nf - the number of fields
    3148: . uOff - the offset into u[] and u_t[] for each field
    3149: . uOff_x - the offset into u_x[] for each field
    3150: . u - each field evaluated at the current point
    3151: . u_t - the time derivative of each field evaluated at the current point
    3152: . u_x - the gradient of each field evaluated at the current point
    3153: . aOff - the offset into a[] and a_t[] for each auxiliary field
    3154: . aOff_x - the offset into a_x[] for each auxiliary field
    3155: . a - each auxiliary field evaluated at the current point
    3156: . a_t - the time derivative of each auxiliary field evaluated at the current point
    3157: . a_x - the gradient of auxiliary each field evaluated at the current point
    3158: . t - current time
    3159: . x - coordinates of the current point
    3160: . numConstants - number of constant parameters
    3161: . constants - constant parameters
    3162: - bcval - output values at the current point

    3164:   Level: developer

    3166: .seealso: PetscDSGetBoundary(), PetscDSSetResidual(), PetscDSSetBdResidual()
    3167: @*/
    3168: PetscErrorCode PetscDSAddBoundary(PetscDS ds, DMBoundaryConditionType type, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(void), void (*bcFunc_t)(void), PetscInt numids, const PetscInt *ids, void *ctx)
    3169: {
    3170:   DSBoundary     b;

    3179:   PetscNew(&b);
    3180:   PetscStrallocpy(name, (char **) &b->name);
    3181:   PetscStrallocpy(labelname, (char **) &b->labelname);
    3182:   PetscMalloc1(numcomps, &b->comps);
    3183:   if (numcomps) {PetscArraycpy(b->comps, comps, numcomps);}
    3184:   PetscMalloc1(numids, &b->ids);
    3185:   if (numids) {PetscArraycpy(b->ids, ids, numids);}
    3186:   b->type            = type;
    3187:   b->field           = field;
    3188:   b->numcomps        = numcomps;
    3189:   b->func            = bcFunc;
    3190:   b->func_t          = bcFunc_t;
    3191:   b->numids          = numids;
    3192:   b->ctx             = ctx;
    3193:   b->next            = ds->boundary;
    3194:   ds->boundary       = b;
    3195:   return(0);
    3196: }

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

    3201:   Input Parameters:
    3202: + ds          - The PetscDS object
    3203: . bd          - The boundary condition number
    3204: . type        - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
    3205: . name        - The BC name
    3206: . labelname   - The label defining constrained points
    3207: . field       - The field to constrain
    3208: . numcomps    - The number of constrained field components
    3209: . comps       - An array of constrained component numbers
    3210: . bcFunc      - A pointwise function giving boundary values
    3211: . bcFunc_t    - A pointwise function giving the time derviative of the boundary values, or NULL
    3212: . numids      - The number of DMLabel ids for constrained points
    3213: . ids         - An array of ids for constrained points
    3214: - ctx         - An optional user context for bcFunc

    3216:   Note:
    3217:   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.

    3219:   Level: developer

    3221: .seealso: PetscDSAddBoundary(), PetscDSGetBoundary(), PetscDSGetNumBoundary()
    3222: @*/
    3223: PetscErrorCode PetscDSUpdateBoundary(PetscDS ds, PetscInt bd, DMBoundaryConditionType type, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(void), void (*bcFunc_t)(void), PetscInt numids, const PetscInt *ids, void *ctx)
    3224: {
    3225:   DSBoundary     b = ds->boundary;
    3226:   PetscInt       n = 0;

    3231:   while (b) {
    3232:     if (n == bd) break;
    3233:     b = b->next;
    3234:     ++n;
    3235:   }
    3236:   if (!b) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n);
    3237:   if (name) {
    3238:     PetscFree(b->name);
    3239:     PetscStrallocpy(name, (char **) &b->name);
    3240:   }
    3241:   if (labelname) {
    3242:     PetscFree(b->labelname);
    3243:     PetscStrallocpy(labelname, (char **) &b->labelname);
    3244:   }
    3245:   if (numcomps >= 0 && numcomps != b->numcomps) {
    3246:     b->numcomps = numcomps;
    3247:     PetscFree(b->comps);
    3248:     PetscMalloc1(numcomps, &b->comps);
    3249:     if (numcomps) {PetscArraycpy(b->comps, comps, numcomps);}
    3250:   }
    3251:   if (numids >= 0 && numids != b->numids) {
    3252:     b->numids = numids;
    3253:     PetscFree(b->ids);
    3254:     PetscMalloc1(numids, &b->ids);
    3255:     if (numids) {PetscArraycpy(b->ids, ids, numids);}
    3256:   }
    3257:   b->type = type;
    3258:   if (field >= 0) {b->field  = field;}
    3259:   if (bcFunc)     {b->func   = bcFunc;}
    3260:   if (bcFunc_t)   {b->func_t = bcFunc_t;}
    3261:   if (ctx)        {b->ctx    = ctx;}
    3262:   return(0);
    3263: }

    3265: /*@
    3266:   PetscDSGetNumBoundary - Get the number of registered BC

    3268:   Input Parameters:
    3269: . ds - The PetscDS object

    3271:   Output Parameters:
    3272: . numBd - The number of BC

    3274:   Level: intermediate

    3276: .seealso: PetscDSAddBoundary(), PetscDSGetBoundary()
    3277: @*/
    3278: PetscErrorCode PetscDSGetNumBoundary(PetscDS ds, PetscInt *numBd)
    3279: {
    3280:   DSBoundary b = ds->boundary;

    3285:   *numBd = 0;
    3286:   while (b) {++(*numBd); b = b->next;}
    3287:   return(0);
    3288: }

    3290: /*@C
    3291:   PetscDSGetBoundary - Gets a boundary condition to the model

    3293:   Input Parameters:
    3294: + ds          - The PetscDS object
    3295: - bd          - The BC number

    3297:   Output Parameters:
    3298: + type        - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
    3299: . name        - The BC name
    3300: . labelname   - The label defining constrained points
    3301: . field       - The field to constrain
    3302: . numcomps    - The number of constrained field components
    3303: . comps       - An array of constrained component numbers
    3304: . bcFunc      - A pointwise function giving boundary values
    3305: . bcFunc_t    - A pointwise function giving the time derviative of the boundary values
    3306: . numids      - The number of DMLabel ids for constrained points
    3307: . ids         - An array of ids for constrained points
    3308: - ctx         - An optional user context for bcFunc

    3310:   Options Database Keys:
    3311: + -bc_<boundary name> <num> - Overrides the boundary ids
    3312: - -bc_<boundary name>_comp <num> - Overrides the boundary components

    3314:   Level: developer

    3316: .seealso: PetscDSAddBoundary()
    3317: @*/
    3318: PetscErrorCode PetscDSGetBoundary(PetscDS ds, PetscInt bd, DMBoundaryConditionType *type, const char **name, const char **labelname, PetscInt *field, PetscInt *numcomps, const PetscInt **comps, void (**func)(void), void (**func_t)(void), PetscInt *numids, const PetscInt **ids, void **ctx)
    3319: {
    3320:   DSBoundary b    = ds->boundary;
    3321:   PetscInt   n    = 0;

    3325:   while (b) {
    3326:     if (n == bd) break;
    3327:     b = b->next;
    3328:     ++n;
    3329:   }
    3330:   if (!b) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n);
    3331:   if (type) {
    3333:     *type = b->type;
    3334:   }
    3335:   if (name) {
    3337:     *name = b->name;
    3338:   }
    3339:   if (labelname) {
    3341:     *labelname = b->labelname;
    3342:   }
    3343:   if (field) {
    3345:     *field = b->field;
    3346:   }
    3347:   if (numcomps) {
    3349:     *numcomps = b->numcomps;
    3350:   }
    3351:   if (comps) {
    3353:     *comps = b->comps;
    3354:   }
    3355:   if (func) {
    3357:     *func = b->func;
    3358:   }
    3359:   if (func_t) {
    3361:     *func_t = b->func_t;
    3362:   }
    3363:   if (numids) {
    3365:     *numids = b->numids;
    3366:   }
    3367:   if (ids) {
    3369:     *ids = b->ids;
    3370:   }
    3371:   if (ctx) {
    3373:     *ctx = b->ctx;
    3374:   }
    3375:   return(0);
    3376: }

    3378: /*@
    3379:   PetscDSCopyBoundary - Copy all boundary condition objects to the new problem

    3381:   Not collective

    3383:   Input Parameters:
    3384: + ds        - The source PetscDS object
    3385: . numFields - The number of selected fields, or PETSC_DEFAULT for all fields
    3386: - fields    - The selected fields, or NULL for all fields

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

    3391:   Level: intermediate

    3393: .seealso: PetscDSCopyEquations(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
    3394: @*/
    3395: PetscErrorCode PetscDSCopyBoundary(PetscDS ds, PetscInt numFields, const PetscInt fields[], PetscDS newds)
    3396: {
    3397:   DSBoundary     b, next, *lastnext;

    3403:   if (ds == newds) return(0);
    3404:   next = newds->boundary;
    3405:   while (next) {
    3406:     DSBoundary b = next;

    3408:     next = b->next;
    3409:     PetscFree(b->comps);
    3410:     PetscFree(b->ids);
    3411:     PetscFree(b->name);
    3412:     PetscFree(b->labelname);
    3413:     PetscFree(b);
    3414:   }
    3415:   lastnext = &(newds->boundary);
    3416:   for (b = ds->boundary; b; b = b->next) {
    3417:     DSBoundary bNew;
    3418:     PetscInt   fieldNew = -1;

    3420:     if (numFields > 0 && fields) {
    3421:       PetscInt f;

    3423:       for (f = 0; f < numFields; ++f) if (b->field == fields[f]) break;
    3424:       if (f == numFields) continue;
    3425:       fieldNew = f;
    3426:     }
    3427:     PetscNew(&bNew);
    3428:     bNew->numcomps = b->numcomps;
    3429:     PetscMalloc1(bNew->numcomps, &bNew->comps);
    3430:     PetscArraycpy(bNew->comps, b->comps, bNew->numcomps);
    3431:     bNew->numids = b->numids;
    3432:     PetscMalloc1(bNew->numids, &bNew->ids);
    3433:     PetscArraycpy(bNew->ids, b->ids, bNew->numids);
    3434:     PetscStrallocpy(b->labelname,(char **) &(bNew->labelname));
    3435:     PetscStrallocpy(b->name,(char **) &(bNew->name));
    3436:     bNew->ctx   = b->ctx;
    3437:     bNew->type  = b->type;
    3438:     bNew->field = fieldNew < 0 ? b->field : fieldNew;
    3439:     bNew->func  = b->func;

    3441:     *lastnext = bNew;
    3442:     lastnext = &(bNew->next);
    3443:   }
    3444:   return(0);
    3445: }

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

    3450:   Not collective

    3452:   Input Parameter:
    3453: + prob - The PetscDS object
    3454: . numFields - Number of new fields
    3455: - fields - Old field number for each new field

    3457:   Output Parameter:
    3458: . newprob - The PetscDS copy

    3460:   Level: intermediate

    3462: .seealso: PetscDSSelectEquations(), PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
    3463: @*/
    3464: PetscErrorCode PetscDSSelectDiscretizations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob)
    3465: {
    3466:   PetscInt       Nf, Nfn, fn;

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

    3480:     if (f >= Nf) continue;
    3481:     PetscDSGetDiscretization(prob, f, &disc);
    3482:     PetscDSSetDiscretization(newprob, fn, disc);
    3483:   }
    3484:   return(0);
    3485: }

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

    3490:   Not collective

    3492:   Input Parameter:
    3493: + prob - The PetscDS object
    3494: . numFields - Number of new fields
    3495: - fields - Old field number for each new field

    3497:   Output Parameter:
    3498: . newprob - The PetscDS copy

    3500:   Level: intermediate

    3502: .seealso: PetscDSSelectDiscretizations(), PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
    3503: @*/
    3504: PetscErrorCode PetscDSSelectEquations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob)
    3505: {
    3506:   PetscInt       Nf, Nfn, fn, gn;

    3513:   PetscDSGetNumFields(prob, &Nf);
    3514:   PetscDSGetNumFields(newprob, &Nfn);
    3515:   if (numFields > Nfn) SETERRQ2(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_SIZ, "Number of fields %D to transfer must not be greater then the total number of fields %D", numFields, Nfn);
    3516:   for (fn = 0; fn < numFields; ++fn) {
    3517:     const PetscInt   f = fields ? fields[fn] : fn;
    3518:     PetscPointFunc   obj;
    3519:     PetscPointFunc   f0, f1;
    3520:     PetscBdPointFunc f0Bd, f1Bd;
    3521:     PetscRiemannFunc r;

    3523:     if (f >= Nf) continue;
    3524:     PetscDSGetObjective(prob, f, &obj);
    3525:     PetscDSGetResidual(prob, f, &f0, &f1);
    3526:     PetscDSGetBdResidual(prob, f, &f0Bd, &f1Bd);
    3527:     PetscDSGetRiemannSolver(prob, f, &r);
    3528:     PetscDSSetObjective(newprob, fn, obj);
    3529:     PetscDSSetResidual(newprob, fn, f0, f1);
    3530:     PetscDSSetBdResidual(newprob, fn, f0Bd, f1Bd);
    3531:     PetscDSSetRiemannSolver(newprob, fn, r);
    3532:     for (gn = 0; gn < numFields; ++gn) {
    3533:       const PetscInt  g = fields ? fields[gn] : gn;
    3534:       PetscPointJac   g0, g1, g2, g3;
    3535:       PetscPointJac   g0p, g1p, g2p, g3p;
    3536:       PetscBdPointJac g0Bd, g1Bd, g2Bd, g3Bd;

    3538:       if (g >= Nf) continue;
    3539:       PetscDSGetJacobian(prob, f, g, &g0, &g1, &g2, &g3);
    3540:       PetscDSGetJacobianPreconditioner(prob, f, g, &g0p, &g1p, &g2p, &g3p);
    3541:       PetscDSGetBdJacobian(prob, f, g, &g0Bd, &g1Bd, &g2Bd, &g3Bd);
    3542:       PetscDSSetJacobian(newprob, fn, gn, g0, g1, g2, g3);
    3543:       PetscDSSetJacobianPreconditioner(newprob, fn, gn, g0p, g1p, g2p, g3p);
    3544:       PetscDSSetBdJacobian(newprob, fn, gn, g0Bd, g1Bd, g2Bd, g3Bd);
    3545:     }
    3546:   }
    3547:   return(0);
    3548: }

    3550: /*@
    3551:   PetscDSCopyEquations - Copy all pointwise function pointers to the new problem

    3553:   Not collective

    3555:   Input Parameter:
    3556: . prob - The PetscDS object

    3558:   Output Parameter:
    3559: . newprob - The PetscDS copy

    3561:   Level: intermediate

    3563: .seealso: PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
    3564: @*/
    3565: PetscErrorCode PetscDSCopyEquations(PetscDS prob, PetscDS newprob)
    3566: {
    3567:   PetscInt       Nf, Ng;

    3573:   PetscDSGetNumFields(prob, &Nf);
    3574:   PetscDSGetNumFields(newprob, &Ng);
    3575:   if (Nf != Ng) SETERRQ2(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_SIZ, "Number of fields must match %D != %D", Nf, Ng);
    3576:   PetscDSSelectEquations(prob, Nf, NULL, newprob);
    3577:   return(0);
    3578: }
    3579: /*@
    3580:   PetscDSCopyConstants - Copy all constants to the new problem

    3582:   Not collective

    3584:   Input Parameter:
    3585: . prob - The PetscDS object

    3587:   Output Parameter:
    3588: . newprob - The PetscDS copy

    3590:   Level: intermediate

    3592: .seealso: PetscDSCopyBoundary(), PetscDSCopyEquations(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
    3593: @*/
    3594: PetscErrorCode PetscDSCopyConstants(PetscDS prob, PetscDS newprob)
    3595: {
    3596:   PetscInt           Nc;
    3597:   const PetscScalar *constants;
    3598:   PetscErrorCode     ierr;

    3603:   PetscDSGetConstants(prob, &Nc, &constants);
    3604:   PetscDSSetConstants(newprob, Nc, (PetscScalar *) constants);
    3605:   return(0);
    3606: }

    3608: PetscErrorCode PetscDSGetHeightSubspace(PetscDS prob, PetscInt height, PetscDS *subprob)
    3609: {
    3610:   PetscInt       dim, Nf, f;

    3616:   if (height == 0) {*subprob = prob; return(0);}
    3617:   PetscDSGetNumFields(prob, &Nf);
    3618:   PetscDSGetSpatialDimension(prob, &dim);
    3619:   if (height > dim) SETERRQ2(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_OUTOFRANGE, "DS can only handle height in [0, %D], not %D", dim, height);
    3620:   if (!prob->subprobs) {PetscCalloc1(dim, &prob->subprobs);}
    3621:   if (!prob->subprobs[height-1]) {
    3622:     PetscInt cdim;

    3624:     PetscDSCreate(PetscObjectComm((PetscObject) prob), &prob->subprobs[height-1]);
    3625:     PetscDSGetCoordinateDimension(prob, &cdim);
    3626:     PetscDSSetCoordinateDimension(prob->subprobs[height-1], cdim);
    3627:     for (f = 0; f < Nf; ++f) {
    3628:       PetscFE      subfe;
    3629:       PetscObject  obj;
    3630:       PetscClassId id;

    3632:       PetscDSGetDiscretization(prob, f, &obj);
    3633:       PetscObjectGetClassId(obj, &id);
    3634:       if (id == PETSCFE_CLASSID) {PetscFEGetHeightSubspace((PetscFE) obj, height, &subfe);}
    3635:       else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unsupported discretization type for field %d", f);
    3636:       PetscDSSetDiscretization(prob->subprobs[height-1], f, (PetscObject) subfe);
    3637:     }
    3638:   }
    3639:   *subprob = prob->subprobs[height-1];
    3640:   return(0);
    3641: }

    3643: PetscErrorCode PetscDSGetDiscType_Internal(PetscDS ds, PetscInt f, PetscDiscType *disctype)
    3644: {
    3645:   PetscObject    obj;
    3646:   PetscClassId   id;
    3647:   PetscInt       Nf;

    3653:   *disctype = PETSC_DISC_NONE;
    3654:   PetscDSGetNumFields(ds, &Nf);
    3655:   if (f >= Nf) SETERRQ2(PetscObjectComm((PetscObject) ds), PETSC_ERR_ARG_SIZ, "Field %D must be in [0, %D)", f, Nf);
    3656:   PetscDSGetDiscretization(ds, f, &obj);
    3657:   if (obj) {
    3658:     PetscObjectGetClassId(obj, &id);
    3659:     if (id == PETSCFE_CLASSID) *disctype = PETSC_DISC_FE;
    3660:     else                       *disctype = PETSC_DISC_FV;
    3661:   }
    3662:   return(0);
    3663: }

    3665: static PetscErrorCode PetscDSDestroy_Basic(PetscDS ds)
    3666: {

    3670:   PetscFree(ds->data);
    3671:   return(0);
    3672: }

    3674: static PetscErrorCode PetscDSInitialize_Basic(PetscDS ds)
    3675: {
    3677:   ds->ops->setfromoptions = NULL;
    3678:   ds->ops->setup          = NULL;
    3679:   ds->ops->view           = NULL;
    3680:   ds->ops->destroy        = PetscDSDestroy_Basic;
    3681:   return(0);
    3682: }

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

    3687:   Level: intermediate

    3689: .seealso: PetscDSType, PetscDSCreate(), PetscDSSetType()
    3690: M*/

    3692: PETSC_EXTERN PetscErrorCode PetscDSCreate_Basic(PetscDS ds)
    3693: {
    3694:   PetscDS_Basic *b;

    3699:   PetscNewLog(ds, &b);
    3700:   ds->data = b;

    3702:   PetscDSInitialize_Basic(ds);
    3703:   return(0);
    3704: }