Actual source code: dtds.c

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

  3: PetscClassId PETSCDS_CLASSID = 0;

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

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

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

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

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

 24:   Not Collective

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

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

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

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

 48:   Level: advanced

 50:    Not available from Fortran

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

 54: @*/
 55: PetscErrorCode PetscDSRegister(const char sname[], PetscErrorCode (*function)(PetscDS))
 56: {
 57:   PetscFunctionListAdd(&PetscDSList, sname, function);
 58:   return 0;
 59: }

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

 64:   Collective on prob

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

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

 73:   Level: intermediate

 75:    Not available from Fortran

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

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

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

 92:   PetscTryTypeMethod(prob, destroy);
 93:   prob->ops->destroy = NULL;

 95:   (*r)(prob);
 96:   PetscObjectChangeTypeName((PetscObject)prob, name);
 97:   return 0;
 98: }

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

103:   Not Collective

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

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

111:   Level: intermediate

113:    Not available from Fortran

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

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

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

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

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

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

231: /*@C
232:    PetscDSViewFromOptions - View from Options

234:    Collective on PetscDS

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

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

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

254:   Collective on prob

256:   Input Parameters:
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;

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

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

280:   Collective on prob

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

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

292:   Level: developer

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

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

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

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

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

356:   Collective on prob

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

361:   Level: developer

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

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

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

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

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

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

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

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

516: /*@
517:   PetscDSDestroy - Destroys a PetscDS object

519:   Collective on prob

521:   Input Parameter:
522: . prob - the PetscDS object to destroy

524:   Level: developer

526: .seealso `PetscDSView()`
527: @*/
528: PetscErrorCode PetscDSDestroy(PetscDS *ds)
529: {
530:   PetscInt f;

532:   if (!*ds) return 0;

535:   if (--((PetscObject)(*ds))->refct > 0) {
536:     *ds = NULL;
537:     return 0;
538:   }
539:   ((PetscObject)(*ds))->refct = 0;
540:   if ((*ds)->subprobs) {
541:     PetscInt dim, d;

543:     PetscDSGetSpatialDimension(*ds, &dim);
544:     for (d = 0; d < dim; ++d) PetscDSDestroy(&(*ds)->subprobs[d]);
545:   }
546:   PetscFree((*ds)->subprobs);
547:   PetscDSDestroyStructs_Static(*ds);
548:   for (f = 0; f < (*ds)->Nf; ++f) PetscObjectDereference((*ds)->disc[f]);
549:   PetscFree4((*ds)->disc, (*ds)->implicit, (*ds)->cohesive, (*ds)->jetDegree);
550:   PetscWeakFormDestroy(&(*ds)->wf);
551:   PetscFree2((*ds)->update, (*ds)->ctx);
552:   PetscFree4((*ds)->exactSol, (*ds)->exactCtx, (*ds)->exactSol_t, (*ds)->exactCtx_t);
553:   PetscTryTypeMethod((*ds), destroy);
554:   PetscDSDestroyBoundary(*ds);
555:   PetscFree((*ds)->constants);
556:   PetscHeaderDestroy(ds);
557:   return 0;
558: }

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

563:   Collective

565:   Input Parameter:
566: . comm - The communicator for the PetscDS object

568:   Output Parameter:
569: . ds   - The PetscDS object

571:   Level: beginner

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

580:   *ds = NULL;
581:   PetscDSInitializePackage();

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

585:   p->Nf           = 0;
586:   p->setup        = PETSC_FALSE;
587:   p->numConstants = 0;
588:   p->constants    = NULL;
589:   p->dimEmbed     = -1;
590:   p->useJacPre    = PETSC_TRUE;
591:   PetscWeakFormCreate(comm, &p->wf);

593:   *ds = p;
594:   return 0;
595: }

597: /*@
598:   PetscDSGetNumFields - Returns the number of fields in the DS

600:   Not collective

602:   Input Parameter:
603: . prob - The PetscDS object

605:   Output Parameter:
606: . Nf - The number of fields

608:   Level: beginner

610: .seealso: `PetscDSGetSpatialDimension()`, `PetscDSCreate()`
611: @*/
612: PetscErrorCode PetscDSGetNumFields(PetscDS prob, PetscInt *Nf)
613: {
616:   *Nf = prob->Nf;
617:   return 0;
618: }

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

623:   Not collective

625:   Input Parameter:
626: . prob - The PetscDS object

628:   Output Parameter:
629: . dim - The spatial dimension

631:   Level: beginner

633: .seealso: `PetscDSGetCoordinateDimension()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
634: @*/
635: PetscErrorCode PetscDSGetSpatialDimension(PetscDS prob, PetscInt *dim)
636: {
639:   *dim = 0;
640:   if (prob->Nf) {
641:     PetscObject  obj;
642:     PetscClassId id;

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

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

658:   Not collective

660:   Input Parameter:
661: . prob - The PetscDS object

663:   Output Parameter:
664: . dimEmbed - The coordinate dimension

666:   Level: beginner

668: .seealso: `PetscDSSetCoordinateDimension()`, `PetscDSGetSpatialDimension()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
669: @*/
670: PetscErrorCode PetscDSGetCoordinateDimension(PetscDS prob, PetscInt *dimEmbed)
671: {
675:   *dimEmbed = prob->dimEmbed;
676:   return 0;
677: }

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

682:   Logically collective on prob

684:   Input Parameters:
685: + prob - The PetscDS object
686: - dimEmbed - The coordinate dimension

688:   Level: beginner

690: .seealso: `PetscDSGetCoordinateDimension()`, `PetscDSGetSpatialDimension()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
691: @*/
692: PetscErrorCode PetscDSSetCoordinateDimension(PetscDS prob, PetscInt dimEmbed)
693: {
696:   prob->dimEmbed = dimEmbed;
697:   return 0;
698: }

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

703:   Not collective

705:   Input Parameter:
706: . ds - The PetscDS object

708:   Output Parameter:
709: . isCohesive - The flag

711:   Level: developer

713: .seealso: `PetscDSGetNumCohesive()`, `PetscDSGetCohesive()`, `PetscDSSetCohesive()`, `PetscDSCreate()`
714: @*/
715: PetscErrorCode PetscDSIsCohesive(PetscDS ds, PetscBool *isCohesive)
716: {
719:   *isCohesive = ds->isCohesive;
720:   return 0;
721: }

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

726:   Not collective

728:   Input Parameter:
729: . ds - The PetscDS object

731:   Output Parameter:
732: . numCohesive - The number of cohesive fields

734:   Level: developer

736: .seealso: `PetscDSSetCohesive()`, `PetscDSCreate()`
737: @*/
738: PetscErrorCode PetscDSGetNumCohesive(PetscDS ds, PetscInt *numCohesive)
739: {
740:   PetscInt f;

744:   *numCohesive = 0;
745:   for (f = 0; f < ds->Nf; ++f) *numCohesive += ds->cohesive[f] ? 1 : 0;
746:   return 0;
747: }

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

752:   Not collective

754:   Input Parameters:
755: + ds - The PetscDS object
756: - f  - The field index

758:   Output Parameter:
759: . isCohesive - The flag

761:   Level: developer

763: .seealso: `PetscDSSetCohesive()`, `PetscDSIsCohesive()`, `PetscDSCreate()`
764: @*/
765: PetscErrorCode PetscDSGetCohesive(PetscDS ds, PetscInt f, PetscBool *isCohesive)
766: {
770:   *isCohesive = ds->cohesive[f];
771:   return 0;
772: }

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

777:   Not collective

779:   Input Parameters:
780: + ds - The PetscDS object
781: . f  - The field index
782: - isCohesive - The flag for a cohesive field

784:   Level: developer

786: .seealso: `PetscDSGetCohesive()`, `PetscDSIsCohesive()`, `PetscDSCreate()`
787: @*/
788: PetscErrorCode PetscDSSetCohesive(PetscDS ds, PetscInt f, PetscBool isCohesive)
789: {
790:   PetscInt i;

794:   ds->cohesive[f] = isCohesive;
795:   ds->isCohesive  = PETSC_FALSE;
796:   for (i = 0; i < ds->Nf; ++i) ds->isCohesive = ds->isCohesive || ds->cohesive[f] ? PETSC_TRUE : PETSC_FALSE;
797:   return 0;
798: }

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

803:   Not collective

805:   Input Parameter:
806: . prob - The PetscDS object

808:   Output Parameter:
809: . dim - The total problem dimension

811:   Level: beginner

813: .seealso: `PetscDSGetNumFields()`, `PetscDSCreate()`
814: @*/
815: PetscErrorCode PetscDSGetTotalDimension(PetscDS prob, PetscInt *dim)
816: {
818:   PetscDSSetUp(prob);
820:   *dim = prob->totDim;
821:   return 0;
822: }

824: /*@
825:   PetscDSGetTotalComponents - Returns the total number of components in this system

827:   Not collective

829:   Input Parameter:
830: . prob - The PetscDS object

832:   Output Parameter:
833: . dim - The total number of components

835:   Level: beginner

837: .seealso: `PetscDSGetNumFields()`, `PetscDSCreate()`
838: @*/
839: PetscErrorCode PetscDSGetTotalComponents(PetscDS prob, PetscInt *Nc)
840: {
842:   PetscDSSetUp(prob);
844:   *Nc = prob->totComp;
845:   return 0;
846: }

848: /*@
849:   PetscDSGetDiscretization - Returns the discretization object for the given field

851:   Not collective

853:   Input Parameters:
854: + prob - The PetscDS object
855: - f - The field number

857:   Output Parameter:
858: . disc - The discretization object

860:   Level: beginner

862: .seealso: `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
863: @*/
864: PetscErrorCode PetscDSGetDiscretization(PetscDS prob, PetscInt f, PetscObject *disc)
865: {
870:   *disc = prob->disc[f];
871:   return 0;
872: }

874: /*@
875:   PetscDSSetDiscretization - Sets the discretization object for the given field

877:   Not collective

879:   Input Parameters:
880: + prob - The PetscDS object
881: . f - The field number
882: - disc - The discretization object

884:   Level: beginner

886: .seealso: `PetscDSGetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
887: @*/
888: PetscErrorCode PetscDSSetDiscretization(PetscDS prob, PetscInt f, PetscObject disc)
889: {
893:   PetscDSEnlarge_Static(prob, f + 1);
894:   PetscObjectDereference(prob->disc[f]);
895:   prob->disc[f] = disc;
896:   PetscObjectReference(disc);
897:   if (disc) {
898:     PetscClassId id;

900:     PetscObjectGetClassId(disc, &id);
901:     if (id == PETSCFE_CLASSID) {
902:       PetscDSSetImplicit(prob, f, PETSC_TRUE);
903:     } else if (id == PETSCFV_CLASSID) {
904:       PetscDSSetImplicit(prob, f, PETSC_FALSE);
905:     }
906:     PetscDSSetJetDegree(prob, f, 1);
907:   }
908:   return 0;
909: }

911: /*@
912:   PetscDSGetWeakForm - Returns the weak form object

914:   Not collective

916:   Input Parameter:
917: . ds - The PetscDS object

919:   Output Parameter:
920: . wf - The weak form object

922:   Level: beginner

924: .seealso: `PetscDSSetWeakForm()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
925: @*/
926: PetscErrorCode PetscDSGetWeakForm(PetscDS ds, PetscWeakForm *wf)
927: {
930:   *wf = ds->wf;
931:   return 0;
932: }

934: /*@
935:   PetscDSSetWeakForm - Sets the weak form object

937:   Not collective

939:   Input Parameters:
940: + ds - The PetscDS object
941: - wf - The weak form object

943:   Level: beginner

945: .seealso: `PetscDSGetWeakForm()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
946: @*/
947: PetscErrorCode PetscDSSetWeakForm(PetscDS ds, PetscWeakForm wf)
948: {
951:   PetscObjectDereference((PetscObject)ds->wf);
952:   ds->wf = wf;
953:   PetscObjectReference((PetscObject)wf);
954:   PetscWeakFormSetNumFields(wf, ds->Nf);
955:   return 0;
956: }

958: /*@
959:   PetscDSAddDiscretization - Adds a discretization object

961:   Not collective

963:   Input Parameters:
964: + prob - The PetscDS object
965: - disc - The boundary discretization object

967:   Level: beginner

969: .seealso: `PetscDSGetDiscretization()`, `PetscDSSetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
970: @*/
971: PetscErrorCode PetscDSAddDiscretization(PetscDS prob, PetscObject disc)
972: {
973:   PetscDSSetDiscretization(prob, prob->Nf, disc);
974:   return 0;
975: }

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

980:   Not collective

982:   Input Parameter:
983: . prob - The PetscDS object

985:   Output Parameter:
986: . q - The quadrature object

988: Level: intermediate

990: .seealso: `PetscDSSetImplicit()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
991: @*/
992: PetscErrorCode PetscDSGetQuadrature(PetscDS prob, PetscQuadrature *q)
993: {
994:   PetscObject  obj;
995:   PetscClassId id;

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

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

1010:   Not collective

1012:   Input Parameters:
1013: + prob - The PetscDS object
1014: - f - The field number

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

1019:   Level: developer

1021: .seealso: `PetscDSSetImplicit()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1022: @*/
1023: PetscErrorCode PetscDSGetImplicit(PetscDS prob, PetscInt f, PetscBool *implicit)
1024: {
1028:   *implicit = prob->implicit[f];
1029:   return 0;
1030: }

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

1035:   Not collective

1037:   Input Parameters:
1038: + prob - The PetscDS object
1039: . f - The field number
1040: - implicit - The flag indicating what kind of solve to use for this field

1042:   Level: developer

1044: .seealso: `PetscDSGetImplicit()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1045: @*/
1046: PetscErrorCode PetscDSSetImplicit(PetscDS prob, PetscInt f, PetscBool implicit)
1047: {
1050:   prob->implicit[f] = implicit;
1051:   return 0;
1052: }

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

1057:   Not collective

1059:   Input Parameters:
1060: + ds - The PetscDS object
1061: - f  - The field number

1063:   Output Parameter:
1064: . k  - The highest derivative we need to tabulate

1066:   Level: developer

1068: .seealso: `PetscDSSetJetDegree()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1069: @*/
1070: PetscErrorCode PetscDSGetJetDegree(PetscDS ds, PetscInt f, PetscInt *k)
1071: {
1075:   *k = ds->jetDegree[f];
1076:   return 0;
1077: }

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

1082:   Not collective

1084:   Input Parameters:
1085: + ds - The PetscDS object
1086: . f  - The field number
1087: - k  - The highest derivative we need to tabulate

1089:   Level: developer

1091: .seealso: `PetscDSGetJetDegree()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1092: @*/
1093: PetscErrorCode PetscDSSetJetDegree(PetscDS ds, PetscInt f, PetscInt k)
1094: {
1097:   ds->jetDegree[f] = k;
1098:   return 0;
1099: }

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

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

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

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

1126:   Not collective

1128:   Input Parameters:
1129: + ds - The PetscDS
1130: - f  - The test field number

1132:   Output Parameters:
1133: + f0 - integrand for the test function term
1134: - f1 - integrand for the test function gradient term

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

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

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

1142: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1143: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1144: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1145: $    PetscReal t, const PetscReal x[], PetscScalar f0[])

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

1165:   Level: intermediate

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

1176:   PetscWeakFormGetResidual(ds->wf, NULL, 0, f, 0, &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, void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
1227: {
1232:   PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1);
1233:   return 0;
1234: }

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

1239:   Not collective

1241:   Input Parameters:
1242: + ds - The PetscDS
1243: - f  - The test field number

1245:   Output Parameters:
1246: + f0 - integrand for the test function term
1247: - f1 - integrand for the test function gradient term

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

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

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

1255: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1256: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1257: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1258: $    PetscReal t, const PetscReal x[], PetscScalar f0[])

1260: + dim - the spatial dimension
1261: . Nf - the number of fields
1262: . uOff - the offset into u[] and u_t[] for each field
1263: . uOff_x - the offset into u_x[] for each field
1264: . u - each field evaluated at the current point
1265: . u_t - the time derivative of each field evaluated at the current point
1266: . u_x - the gradient of each field evaluated at the current point
1267: . aOff - the offset into a[] and a_t[] for each auxiliary field
1268: . aOff_x - the offset into a_x[] for each auxiliary field
1269: . a - each auxiliary field evaluated at the current point
1270: . a_t - the time derivative of each auxiliary field evaluated at the current point
1271: . a_x - the gradient of auxiliary each field evaluated at the current point
1272: . t - current time
1273: . x - coordinates of the current point
1274: . numConstants - number of constant parameters
1275: . constants - constant parameters
1276: - f0 - output values at the current point

1278:   Level: intermediate

1280: .seealso: `PetscDSSetRHSResidual()`
1281: @*/
1282: PetscErrorCode PetscDSGetRHSResidual(PetscDS ds, PetscInt f, void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
1283: {
1284:   PetscPointFunc *tmp0, *tmp1;
1285:   PetscInt        n0, n1;

1289:   PetscWeakFormGetResidual(ds->wf, NULL, 0, f, 100, &n0, &tmp0, &n1, &tmp1);
1290:   *f0 = tmp0 ? tmp0[0] : NULL;
1291:   *f1 = tmp1 ? tmp1[0] : NULL;
1292:   return 0;
1293: }

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

1298:   Not collective

1300:   Input Parameters:
1301: + ds - The PetscDS
1302: . f  - The test field number
1303: . f0 - integrand for the test function term
1304: - f1 - integrand for the test function gradient term

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

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

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

1312: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1313: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1314: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1315: $    PetscReal t, const PetscReal x[], PetscScalar f0[])

1317: + dim - the spatial dimension
1318: . Nf - the number of fields
1319: . uOff - the offset into u[] and u_t[] for each field
1320: . uOff_x - the offset into u_x[] for each field
1321: . u - each field evaluated at the current point
1322: . u_t - the time derivative of each field evaluated at the current point
1323: . u_x - the gradient of each field evaluated at the current point
1324: . aOff - the offset into a[] and a_t[] for each auxiliary field
1325: . aOff_x - the offset into a_x[] for each auxiliary field
1326: . a - each auxiliary field evaluated at the current point
1327: . a_t - the time derivative of each auxiliary field evaluated at the current point
1328: . a_x - the gradient of auxiliary each field evaluated at the current point
1329: . t - current time
1330: . x - coordinates of the current point
1331: . numConstants - number of constant parameters
1332: . constants - constant parameters
1333: - f0 - output values at the current point

1335:   Level: intermediate

1337: .seealso: `PetscDSGetResidual()`
1338: @*/
1339: PetscErrorCode PetscDSSetRHSResidual(PetscDS ds, PetscInt f, void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
1340: {
1345:   PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 100, 0, f0, 0, f1);
1346:   return 0;
1347: }

1349: /*@C
1350:   PetscDSHasJacobian - Signals that Jacobian functions have been set

1352:   Not collective

1354:   Input Parameter:
1355: . prob - The PetscDS

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

1360:   Level: intermediate

1362: .seealso: `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`
1363: @*/
1364: PetscErrorCode PetscDSHasJacobian(PetscDS ds, PetscBool *hasJac)
1365: {
1367:   PetscWeakFormHasJacobian(ds->wf, hasJac);
1368:   return 0;
1369: }

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

1374:   Not collective

1376:   Input Parameters:
1377: + ds - The PetscDS
1378: . f  - The test field number
1379: - g  - The field number

1381:   Output Parameters:
1382: + g0 - integrand for the test and basis function term
1383: . g1 - integrand for the test function and basis function gradient term
1384: . g2 - integrand for the test function gradient and basis function term
1385: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

1393: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1394: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1395: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1396: $    PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])

1398: + dim - the spatial dimension
1399: . Nf - the number of fields
1400: . uOff - the offset into u[] and u_t[] for each field
1401: . uOff_x - the offset into u_x[] for each field
1402: . u - each field evaluated at the current point
1403: . u_t - the time derivative of each field evaluated at the current point
1404: . u_x - the gradient of each field evaluated at the current point
1405: . aOff - the offset into a[] and a_t[] for each auxiliary field
1406: . aOff_x - the offset into a_x[] for each auxiliary field
1407: . a - each auxiliary field evaluated at the current point
1408: . a_t - the time derivative of each auxiliary field evaluated at the current point
1409: . a_x - the gradient of auxiliary each field evaluated at the current point
1410: . t - current time
1411: . u_tShift - the multiplier a for dF/dU_t
1412: . x - coordinates of the current point
1413: . numConstants - number of constant parameters
1414: . constants - constant parameters
1415: - g0 - output values at the current point

1417:   Level: intermediate

1419: .seealso: `PetscDSSetJacobian()`
1420: @*/
1421: PetscErrorCode PetscDSGetJacobian(PetscDS ds, PetscInt f, PetscInt g, void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1422: {
1423:   PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
1424:   PetscInt       n0, n1, n2, n3;

1429:   PetscWeakFormGetJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);
1430:   *g0 = tmp0 ? tmp0[0] : NULL;
1431:   *g1 = tmp1 ? tmp1[0] : NULL;
1432:   *g2 = tmp2 ? tmp2[0] : NULL;
1433:   *g3 = tmp3 ? tmp3[0] : NULL;
1434:   return 0;
1435: }

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

1440:   Not collective

1442:   Input Parameters:
1443: + ds - The PetscDS
1444: . f  - The test field number
1445: . g  - The field number
1446: . g0 - integrand for the test and basis function term
1447: . g1 - integrand for the test function and basis function gradient term
1448: . g2 - integrand for the test function gradient and basis function term
1449: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

1457: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1458: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1459: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1460: $    PetscReal t, const PetscReal x[], PetscScalar g0[])

1462: + dim - the spatial dimension
1463: . Nf - the number of fields
1464: . uOff - the offset into u[] and u_t[] for each field
1465: . uOff_x - the offset into u_x[] for each field
1466: . u - each field evaluated at the current point
1467: . u_t - the time derivative of each field evaluated at the current point
1468: . u_x - the gradient of each field evaluated at the current point
1469: . aOff - the offset into a[] and a_t[] for each auxiliary field
1470: . aOff_x - the offset into a_x[] for each auxiliary field
1471: . a - each auxiliary field evaluated at the current point
1472: . a_t - the time derivative of each auxiliary field evaluated at the current point
1473: . a_x - the gradient of auxiliary each field evaluated at the current point
1474: . t - current time
1475: . u_tShift - the multiplier a for dF/dU_t
1476: . x - coordinates of the current point
1477: . numConstants - number of constant parameters
1478: . constants - constant parameters
1479: - g0 - output values at the current point

1481:   Level: intermediate

1483: .seealso: `PetscDSGetJacobian()`
1484: @*/
1485: PetscErrorCode PetscDSSetJacobian(PetscDS ds, PetscInt f, PetscInt g, void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1486: {
1494:   PetscWeakFormSetIndexJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);
1495:   return 0;
1496: }

1498: /*@C
1499:   PetscDSUseJacobianPreconditioner - Whether to construct a Jacobian preconditioner

1501:   Not collective

1503:   Input Parameters:
1504: + prob - The PetscDS
1505: - useJacPre - flag that enables construction of a Jacobian preconditioner

1507:   Level: intermediate

1509: .seealso: `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`
1510: @*/
1511: PetscErrorCode PetscDSUseJacobianPreconditioner(PetscDS prob, PetscBool useJacPre)
1512: {
1514:   prob->useJacPre = useJacPre;
1515:   return 0;
1516: }

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

1521:   Not collective

1523:   Input Parameter:
1524: . prob - The PetscDS

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

1529:   Level: intermediate

1531: .seealso: `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`
1532: @*/
1533: PetscErrorCode PetscDSHasJacobianPreconditioner(PetscDS ds, PetscBool *hasJacPre)
1534: {
1536:   *hasJacPre = PETSC_FALSE;
1537:   if (!ds->useJacPre) return 0;
1538:   PetscWeakFormHasJacobianPreconditioner(ds->wf, hasJacPre);
1539:   return 0;
1540: }

1542: /*@C
1543:   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.

1545:   Not collective

1547:   Input Parameters:
1548: + ds - The PetscDS
1549: . f  - The test field number
1550: - g  - The field number

1552:   Output Parameters:
1553: + g0 - integrand for the test and basis function term
1554: . g1 - integrand for the test function and basis function gradient term
1555: . g2 - integrand for the test function gradient and basis function term
1556: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

1564: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1565: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1566: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1567: $    PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])

1569: + dim - the spatial dimension
1570: . Nf - the number of fields
1571: . uOff - the offset into u[] and u_t[] for each field
1572: . uOff_x - the offset into u_x[] for each field
1573: . u - each field evaluated at the current point
1574: . u_t - the time derivative of each field evaluated at the current point
1575: . u_x - the gradient of each field evaluated at the current point
1576: . aOff - the offset into a[] and a_t[] for each auxiliary field
1577: . aOff_x - the offset into a_x[] for each auxiliary field
1578: . a - each auxiliary field evaluated at the current point
1579: . a_t - the time derivative of each auxiliary field evaluated at the current point
1580: . a_x - the gradient of auxiliary each field evaluated at the current point
1581: . t - current time
1582: . u_tShift - the multiplier a for dF/dU_t
1583: . x - coordinates of the current point
1584: . numConstants - number of constant parameters
1585: . constants - constant parameters
1586: - g0 - output values at the current point

1588:   Level: intermediate

1590: .seealso: `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`
1591: @*/
1592: PetscErrorCode PetscDSGetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1593: {
1594:   PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
1595:   PetscInt       n0, n1, n2, n3;

1600:   PetscWeakFormGetJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);
1601:   *g0 = tmp0 ? tmp0[0] : NULL;
1602:   *g1 = tmp1 ? tmp1[0] : NULL;
1603:   *g2 = tmp2 ? tmp2[0] : NULL;
1604:   *g3 = tmp3 ? tmp3[0] : NULL;
1605:   return 0;
1606: }

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

1611:   Not collective

1613:   Input Parameters:
1614: + ds - The PetscDS
1615: . f  - The test field number
1616: . g  - The field number
1617: . g0 - integrand for the test and basis function term
1618: . g1 - integrand for the test function and basis function gradient term
1619: . g2 - integrand for the test function gradient and basis function term
1620: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

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

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

1652:   Level: intermediate

1654: .seealso: `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobian()`
1655: @*/
1656: PetscErrorCode PetscDSSetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1657: {
1665:   PetscWeakFormSetIndexJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);
1666:   return 0;
1667: }

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

1672:   Not collective

1674:   Input Parameter:
1675: . ds - The PetscDS

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

1680:   Level: intermediate

1682: .seealso: `PetscDSGetDynamicJacobian()`, `PetscDSSetDynamicJacobian()`, `PetscDSGetJacobian()`
1683: @*/
1684: PetscErrorCode PetscDSHasDynamicJacobian(PetscDS ds, PetscBool *hasDynJac)
1685: {
1687:   PetscWeakFormHasDynamicJacobian(ds->wf, hasDynJac);
1688:   return 0;
1689: }

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

1694:   Not collective

1696:   Input Parameters:
1697: + ds - The PetscDS
1698: . f  - The test field number
1699: - g  - The field number

1701:   Output Parameters:
1702: + g0 - integrand for the test and basis function term
1703: . g1 - integrand for the test function and basis function gradient term
1704: . g2 - integrand for the test function gradient and basis function term
1705: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

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

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

1737:   Level: intermediate

1739: .seealso: `PetscDSSetJacobian()`
1740: @*/
1741: PetscErrorCode PetscDSGetDynamicJacobian(PetscDS ds, PetscInt f, PetscInt g, void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1742: {
1743:   PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
1744:   PetscInt       n0, n1, n2, n3;

1749:   PetscWeakFormGetDynamicJacobian(ds->wf, NULL, 0, f, g, 0, &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, void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1806: {
1814:   PetscWeakFormSetIndexDynamicJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);
1815:   return 0;
1816: }

1818: /*@C
1819:   PetscDSGetRiemannSolver - Returns the Riemann solver for the given field

1821:   Not collective

1823:   Input Parameters:
1824: + ds - The PetscDS object
1825: - f  - The field number

1827:   Output Parameter:
1828: . r    - Riemann solver

1830:   Calling sequence for r:

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

1834: + dim  - The spatial dimension
1835: . Nf   - The number of fields
1836: . x    - The coordinates at a point on the interface
1837: . n    - The normal vector to the interface
1838: . uL   - The state vector to the left of the interface
1839: . uR   - The state vector to the right of the interface
1840: . flux - output array of flux through the interface
1841: . numConstants - number of constant parameters
1842: . constants - constant parameters
1843: - ctx  - optional user context

1845:   Level: intermediate

1847: .seealso: `PetscDSSetRiemannSolver()`
1848: @*/
1849: PetscErrorCode PetscDSGetRiemannSolver(PetscDS ds, PetscInt f, 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))
1850: {
1851:   PetscRiemannFunc *tmp;
1852:   PetscInt          n;

1857:   PetscWeakFormGetRiemannSolver(ds->wf, NULL, 0, f, 0, &n, &tmp);
1858:   *r = tmp ? tmp[0] : NULL;
1859:   return 0;
1860: }

1862: /*@C
1863:   PetscDSSetRiemannSolver - Sets the Riemann solver for the given field

1865:   Not collective

1867:   Input Parameters:
1868: + ds - The PetscDS object
1869: . f  - The field number
1870: - r  - Riemann solver

1872:   Calling sequence for r:

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

1876: + dim  - The spatial dimension
1877: . Nf   - The number of fields
1878: . x    - The coordinates at a point on the interface
1879: . n    - The normal vector to the interface
1880: . uL   - The state vector to the left of the interface
1881: . uR   - The state vector to the right of the interface
1882: . flux - output array of flux through the interface
1883: . numConstants - number of constant parameters
1884: . constants - constant parameters
1885: - ctx  - optional user context

1887:   Level: intermediate

1889: .seealso: `PetscDSGetRiemannSolver()`
1890: @*/
1891: PetscErrorCode PetscDSSetRiemannSolver(PetscDS ds, PetscInt f, 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))
1892: {
1896:   PetscWeakFormSetIndexRiemannSolver(ds->wf, NULL, 0, f, 0, 0, r);
1897:   return 0;
1898: }

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

1903:   Not collective

1905:   Input Parameters:
1906: + ds - The PetscDS
1907: - f  - The field number

1909:   Output Parameter:
1910: . update - update function

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

1914: $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1915: $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1916: $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1917: $        PetscReal t, const PetscReal x[], PetscScalar uNew[])

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

1935:   Level: intermediate

1937: .seealso: `PetscDSSetUpdate()`, `PetscDSSetResidual()`
1938: @*/
1939: PetscErrorCode PetscDSGetUpdate(PetscDS ds, PetscInt f, void (**update)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[]))
1940: {
1943:   if (update) {
1945:     *update = ds->update[f];
1946:   }
1947:   return 0;
1948: }

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

1953:   Not collective

1955:   Input Parameters:
1956: + ds     - The PetscDS
1957: . f      - The field number
1958: - update - update function

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

1962: $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1963: $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1964: $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1965: $        PetscReal t, const PetscReal x[], PetscScalar uNew[])

1967: + dim - the spatial dimension
1968: . Nf - the number of fields
1969: . uOff - the offset into u[] and u_t[] for each field
1970: . uOff_x - the offset into u_x[] for each field
1971: . u - each field evaluated at the current point
1972: . u_t - the time derivative of each field evaluated at the current point
1973: . u_x - the gradient of each field evaluated at the current point
1974: . aOff - the offset into a[] and a_t[] for each auxiliary field
1975: . aOff_x - the offset into a_x[] for each auxiliary field
1976: . a - each auxiliary field evaluated at the current point
1977: . a_t - the time derivative of each auxiliary field evaluated at the current point
1978: . a_x - the gradient of auxiliary each field evaluated at the current point
1979: . t - current time
1980: . x - coordinates of the current point
1981: - uNew - new field values at the current point

1983:   Level: intermediate

1985: .seealso: `PetscDSGetResidual()`
1986: @*/
1987: PetscErrorCode PetscDSSetUpdate(PetscDS ds, PetscInt f, void (*update)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[]))
1988: {
1992:   PetscDSEnlarge_Static(ds, f + 1);
1993:   ds->update[f] = update;
1994:   return 0;
1995: }

1997: PetscErrorCode PetscDSGetContext(PetscDS ds, PetscInt f, void *ctx)
1998: {
2002:   *(void **)ctx = ds->ctx[f];
2003:   return 0;
2004: }

2006: PetscErrorCode PetscDSSetContext(PetscDS ds, PetscInt f, void *ctx)
2007: {
2010:   PetscDSEnlarge_Static(ds, f + 1);
2011:   ds->ctx[f] = ctx;
2012:   return 0;
2013: }

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

2018:   Not collective

2020:   Input Parameters:
2021: + ds - The PetscDS
2022: - f  - The test field number

2024:   Output Parameters:
2025: + f0 - boundary integrand for the test function term
2026: - f1 - boundary integrand for the test function gradient term

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

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

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

2034: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2035: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2036: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2037: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])

2039: + dim - the spatial dimension
2040: . Nf - the number of fields
2041: . uOff - the offset into u[] and u_t[] for each field
2042: . uOff_x - the offset into u_x[] for each field
2043: . u - each field evaluated at the current point
2044: . u_t - the time derivative of each field evaluated at the current point
2045: . u_x - the gradient of each field evaluated at the current point
2046: . aOff - the offset into a[] and a_t[] for each auxiliary field
2047: . aOff_x - the offset into a_x[] for each auxiliary field
2048: . a - each auxiliary field evaluated at the current point
2049: . a_t - the time derivative of each auxiliary field evaluated at the current point
2050: . a_x - the gradient of auxiliary each field evaluated at the current point
2051: . t - current time
2052: . x - coordinates of the current point
2053: . n - unit normal at the current point
2054: . numConstants - number of constant parameters
2055: . constants - constant parameters
2056: - f0 - output values at the current point

2058:   Level: intermediate

2060: .seealso: `PetscDSSetBdResidual()`
2061: @*/
2062: PetscErrorCode PetscDSGetBdResidual(PetscDS ds, PetscInt f, void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
2063: {
2064:   PetscBdPointFunc *tmp0, *tmp1;
2065:   PetscInt          n0, n1;

2069:   PetscWeakFormGetBdResidual(ds->wf, NULL, 0, f, 0, &n0, &tmp0, &n1, &tmp1);
2070:   *f0 = tmp0 ? tmp0[0] : NULL;
2071:   *f1 = tmp1 ? tmp1[0] : NULL;
2072:   return 0;
2073: }

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

2078:   Not collective

2080:   Input Parameters:
2081: + ds - The PetscDS
2082: . f  - The test field number
2083: . f0 - boundary integrand for the test function term
2084: - f1 - boundary integrand for the test function gradient term

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

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

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

2092: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2093: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2094: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2095: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])

2097: + dim - the spatial dimension
2098: . Nf - the number of fields
2099: . uOff - the offset into u[] and u_t[] for each field
2100: . uOff_x - the offset into u_x[] for each field
2101: . u - each field evaluated at the current point
2102: . u_t - the time derivative of each field evaluated at the current point
2103: . u_x - the gradient of each field evaluated at the current point
2104: . aOff - the offset into a[] and a_t[] for each auxiliary field
2105: . aOff_x - the offset into a_x[] for each auxiliary field
2106: . a - each auxiliary field evaluated at the current point
2107: . a_t - the time derivative of each auxiliary field evaluated at the current point
2108: . a_x - the gradient of auxiliary each field evaluated at the current point
2109: . t - current time
2110: . x - coordinates of the current point
2111: . n - unit normal at the current point
2112: . numConstants - number of constant parameters
2113: . constants - constant parameters
2114: - f0 - output values at the current point

2116:   Level: intermediate

2118: .seealso: `PetscDSGetBdResidual()`
2119: @*/
2120: PetscErrorCode PetscDSSetBdResidual(PetscDS ds, PetscInt f, void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
2121: {
2124:   PetscWeakFormSetIndexBdResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1);
2125:   return 0;
2126: }

2128: /*@
2129:   PetscDSHasBdJacobian - Signals that boundary Jacobian functions have been set

2131:   Not collective

2133:   Input Parameter:
2134: . ds - The PetscDS

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

2139:   Level: intermediate

2141: .seealso: `PetscDSHasJacobian()`, `PetscDSSetBdJacobian()`, `PetscDSGetBdJacobian()`
2142: @*/
2143: PetscErrorCode PetscDSHasBdJacobian(PetscDS ds, PetscBool *hasBdJac)
2144: {
2147:   PetscWeakFormHasBdJacobian(ds->wf, hasBdJac);
2148:   return 0;
2149: }

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

2154:   Not collective

2156:   Input Parameters:
2157: + ds - The PetscDS
2158: . f  - The test field number
2159: - g  - The field number

2161:   Output Parameters:
2162: + g0 - integrand for the test and basis function term
2163: . g1 - integrand for the test function and basis function gradient term
2164: . g2 - integrand for the test function gradient and basis function term
2165: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

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

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

2198:   Level: intermediate

2200: .seealso: `PetscDSSetBdJacobian()`
2201: @*/
2202: PetscErrorCode PetscDSGetBdJacobian(PetscDS ds, PetscInt f, PetscInt g, void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2203: {
2204:   PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3;
2205:   PetscInt         n0, n1, n2, n3;

2210:   PetscWeakFormGetBdJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);
2211:   *g0 = tmp0 ? tmp0[0] : NULL;
2212:   *g1 = tmp1 ? tmp1[0] : NULL;
2213:   *g2 = tmp2 ? tmp2[0] : NULL;
2214:   *g3 = tmp3 ? tmp3[0] : NULL;
2215:   return 0;
2216: }

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

2221:   Not collective

2223:   Input Parameters:
2224: + ds - The PetscDS
2225: . f  - The test field number
2226: . g  - The field number
2227: . g0 - integrand for the test and basis function term
2228: . g1 - integrand for the test function and basis function gradient term
2229: . g2 - integrand for the test function gradient and basis function term
2230: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

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

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

2263:   Level: intermediate

2265: .seealso: `PetscDSGetBdJacobian()`
2266: @*/
2267: PetscErrorCode PetscDSSetBdJacobian(PetscDS ds, PetscInt f, PetscInt g, void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2268: {
2276:   PetscWeakFormSetIndexBdJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);
2277:   return 0;
2278: }

2280: /*@
2281:   PetscDSHasBdJacobianPreconditioner - Signals that boundary Jacobian preconditioner functions have been set

2283:   Not collective

2285:   Input Parameter:
2286: . ds - The PetscDS

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

2291:   Level: intermediate

2293: .seealso: `PetscDSHasJacobian()`, `PetscDSSetBdJacobian()`, `PetscDSGetBdJacobian()`
2294: @*/
2295: PetscErrorCode PetscDSHasBdJacobianPreconditioner(PetscDS ds, PetscBool *hasBdJacPre)
2296: {
2299:   PetscWeakFormHasBdJacobianPreconditioner(ds->wf, hasBdJacPre);
2300:   return 0;
2301: }

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

2306:   Not collective

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

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

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

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

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

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

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

2351:   This is not yet available in Fortran.

2353:   Level: intermediate

2355: .seealso: `PetscDSSetBdJacobianPreconditioner()`
2356: @*/
2357: PetscErrorCode PetscDSGetBdJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2358: {
2359:   PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3;
2360:   PetscInt         n0, n1, n2, n3;

2365:   PetscWeakFormGetBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);
2366:   *g0 = tmp0 ? tmp0[0] : NULL;
2367:   *g1 = tmp1 ? tmp1[0] : NULL;
2368:   *g2 = tmp2 ? tmp2[0] : NULL;
2369:   *g3 = tmp3 ? tmp3[0] : NULL;
2370:   return 0;
2371: }

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

2376:   Not collective

2378:   Input Parameters:
2379: + ds - The PetscDS
2380: . f  - The test field number
2381: . g  - The field number
2382: . g0 - integrand for the test and basis function term
2383: . g1 - integrand for the test function and basis function gradient term
2384: . g2 - integrand for the test function gradient and basis function term
2385: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

2393: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2394: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2395: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2396: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])

2398: + dim - the spatial dimension
2399: . Nf - the number of fields
2400: . NfAux - the number of auxiliary fields
2401: . uOff - the offset into u[] and u_t[] for each field
2402: . uOff_x - the offset into u_x[] for each field
2403: . u - each field evaluated at the current point
2404: . u_t - the time derivative of each field evaluated at the current point
2405: . u_x - the gradient of each field evaluated at the current point
2406: . aOff - the offset into a[] and a_t[] for each auxiliary field
2407: . aOff_x - the offset into a_x[] for each auxiliary field
2408: . a - each auxiliary field evaluated at the current point
2409: . a_t - the time derivative of each auxiliary field evaluated at the current point
2410: . a_x - the gradient of auxiliary each field evaluated at the current point
2411: . t - current time
2412: . u_tShift - the multiplier a for dF/dU_t
2413: . x - coordinates of the current point
2414: . n - normal at the current point
2415: . numConstants - number of constant parameters
2416: . constants - constant parameters
2417: - g0 - output values at the current point

2419:   This is not yet available in Fortran.

2421:   Level: intermediate

2423: .seealso: `PetscDSGetBdJacobianPreconditioner()`
2424: @*/
2425: PetscErrorCode PetscDSSetBdJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2426: {
2434:   PetscWeakFormSetIndexBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);
2435:   return 0;
2436: }

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

2441:   Not collective

2443:   Input Parameters:
2444: + prob - The PetscDS
2445: - f    - The test field number

2447:   Output Parameters:
2448: + exactSol - exact solution for the test field
2449: - exactCtx - exact solution context

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

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

2455: + dim - the spatial dimension
2456: . t - current time
2457: . x - coordinates of the current point
2458: . Nc - the number of field components
2459: . u - the solution field evaluated at the current point
2460: - ctx - a user context

2462:   Level: intermediate

2464: .seealso: `PetscDSSetExactSolution()`, `PetscDSGetExactSolutionTimeDerivative()`
2465: @*/
2466: PetscErrorCode PetscDSGetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx)
2467: {
2470:   if (sol) {
2472:     *sol = prob->exactSol[f];
2473:   }
2474:   if (ctx) {
2476:     *ctx = prob->exactCtx[f];
2477:   }
2478:   return 0;
2479: }

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

2484:   Not collective

2486:   Input Parameters:
2487: + prob - The PetscDS
2488: . f    - The test field number
2489: . sol  - solution function for the test fields
2490: - ctx  - solution context or NULL

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

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

2496: + dim - the spatial dimension
2497: . t - current time
2498: . x - coordinates of the current point
2499: . Nc - the number of field components
2500: . u - the solution field evaluated at the current point
2501: - ctx - a user context

2503:   Level: intermediate

2505: .seealso: `PetscDSGetExactSolution()`
2506: @*/
2507: PetscErrorCode PetscDSSetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx)
2508: {
2511:   PetscDSEnlarge_Static(prob, f + 1);
2512:   if (sol) {
2514:     prob->exactSol[f] = sol;
2515:   }
2516:   if (ctx) {
2518:     prob->exactCtx[f] = ctx;
2519:   }
2520:   return 0;
2521: }

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

2526:   Not collective

2528:   Input Parameters:
2529: + prob - The PetscDS
2530: - f    - The test field number

2532:   Output Parameters:
2533: + exactSol - time derivative of the exact solution for the test field
2534: - exactCtx - time derivative of the exact solution context

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

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

2540: + dim - the spatial dimension
2541: . t - current time
2542: . x - coordinates of the current point
2543: . Nc - the number of field components
2544: . u - the solution field evaluated at the current point
2545: - ctx - a user context

2547:   Level: intermediate

2549: .seealso: `PetscDSSetExactSolutionTimeDerivative()`, `PetscDSGetExactSolution()`
2550: @*/
2551: PetscErrorCode PetscDSGetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx)
2552: {
2555:   if (sol) {
2557:     *sol = prob->exactSol_t[f];
2558:   }
2559:   if (ctx) {
2561:     *ctx = prob->exactCtx_t[f];
2562:   }
2563:   return 0;
2564: }

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

2569:   Not collective

2571:   Input Parameters:
2572: + prob - The PetscDS
2573: . f    - The test field number
2574: . sol  - time derivative of the solution function for the test fields
2575: - ctx  - time derivative of the solution context or NULL

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

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

2581: + dim - the spatial dimension
2582: . t - current time
2583: . x - coordinates of the current point
2584: . Nc - the number of field components
2585: . u - the solution field evaluated at the current point
2586: - ctx - a user context

2588:   Level: intermediate

2590: .seealso: `PetscDSGetExactSolutionTimeDerivative()`, `PetscDSSetExactSolution()`
2591: @*/
2592: PetscErrorCode PetscDSSetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx)
2593: {
2596:   PetscDSEnlarge_Static(prob, f + 1);
2597:   if (sol) {
2599:     prob->exactSol_t[f] = sol;
2600:   }
2601:   if (ctx) {
2603:     prob->exactCtx_t[f] = ctx;
2604:   }
2605:   return 0;
2606: }

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

2611:   Not collective

2613:   Input Parameter:
2614: . prob - The PetscDS object

2616:   Output Parameters:
2617: + numConstants - The number of constants
2618: - constants    - The array of constants, NULL if there are none

2620:   Level: intermediate

2622: .seealso: `PetscDSSetConstants()`, `PetscDSCreate()`
2623: @*/
2624: PetscErrorCode PetscDSGetConstants(PetscDS prob, PetscInt *numConstants, const PetscScalar *constants[])
2625: {
2627:   if (numConstants) {
2629:     *numConstants = prob->numConstants;
2630:   }
2631:   if (constants) {
2633:     *constants = prob->constants;
2634:   }
2635:   return 0;
2636: }

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

2641:   Not collective

2643:   Input Parameters:
2644: + prob         - The PetscDS object
2645: . numConstants - The number of constants
2646: - constants    - The array of constants, NULL if there are none

2648:   Level: intermediate

2650: .seealso: `PetscDSGetConstants()`, `PetscDSCreate()`
2651: @*/
2652: PetscErrorCode PetscDSSetConstants(PetscDS prob, PetscInt numConstants, PetscScalar constants[])
2653: {
2655:   if (numConstants != prob->numConstants) {
2656:     PetscFree(prob->constants);
2657:     prob->numConstants = numConstants;
2658:     if (prob->numConstants) {
2659:       PetscMalloc1(prob->numConstants, &prob->constants);
2660:     } else {
2661:       prob->constants = NULL;
2662:     }
2663:   }
2664:   if (prob->numConstants) {
2666:     PetscArraycpy(prob->constants, constants, prob->numConstants);
2667:   }
2668:   return 0;
2669: }

2671: /*@
2672:   PetscDSGetFieldIndex - Returns the index of the given field

2674:   Not collective

2676:   Input Parameters:
2677: + prob - The PetscDS object
2678: - disc - The discretization object

2680:   Output Parameter:
2681: . f - The field number

2683:   Level: beginner

2685: .seealso: `PetscGetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2686: @*/
2687: PetscErrorCode PetscDSGetFieldIndex(PetscDS prob, PetscObject disc, PetscInt *f)
2688: {
2689:   PetscInt g;

2693:   *f = -1;
2694:   for (g = 0; g < prob->Nf; ++g) {
2695:     if (disc == prob->disc[g]) break;
2696:   }
2698:   *f = g;
2699:   return 0;
2700: }

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

2705:   Not collective

2707:   Input Parameters:
2708: + prob - The PetscDS object
2709: - f - The field number

2711:   Output Parameter:
2712: . size - The size

2714:   Level: beginner

2716: .seealso: `PetscDSGetFieldOffset()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2717: @*/
2718: PetscErrorCode PetscDSGetFieldSize(PetscDS prob, PetscInt f, PetscInt *size)
2719: {
2723:   PetscDSSetUp(prob);
2724:   *size = prob->Nb[f];
2725:   return 0;
2726: }

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

2731:   Not collective

2733:   Input Parameters:
2734: + prob - The PetscDS object
2735: - f - The field number

2737:   Output Parameter:
2738: . off - The offset

2740:   Level: beginner

2742: .seealso: `PetscDSGetFieldSize()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2743: @*/
2744: PetscErrorCode PetscDSGetFieldOffset(PetscDS prob, PetscInt f, PetscInt *off)
2745: {
2746:   PetscInt size, g;

2751:   *off = 0;
2752:   for (g = 0; g < f; ++g) {
2753:     PetscDSGetFieldSize(prob, g, &size);
2754:     *off += size;
2755:   }
2756:   return 0;
2757: }

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

2762:   Not collective

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

2768:   Output Parameter:
2769: . off - The offset

2771:   Level: beginner

2773: .seealso: `PetscDSGetFieldSize()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2774: @*/
2775: PetscErrorCode PetscDSGetFieldOffsetCohesive(PetscDS ds, PetscInt f, PetscInt *off)
2776: {
2777:   PetscInt size, g;

2782:   *off = 0;
2783:   for (g = 0; g < f; ++g) {
2784:     PetscBool cohesive;

2786:     PetscDSGetCohesive(ds, g, &cohesive);
2787:     PetscDSGetFieldSize(ds, g, &size);
2788:     *off += cohesive ? size : size * 2;
2789:   }
2790:   return 0;
2791: }

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

2796:   Not collective

2798:   Input Parameter:
2799: . prob - The PetscDS object

2801:   Output Parameter:
2802: . dimensions - The number of dimensions

2804:   Level: beginner

2806: .seealso: `PetscDSGetComponentOffsets()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2807: @*/
2808: PetscErrorCode PetscDSGetDimensions(PetscDS prob, PetscInt *dimensions[])
2809: {
2811:   PetscDSSetUp(prob);
2813:   *dimensions = prob->Nb;
2814:   return 0;
2815: }

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

2820:   Not collective

2822:   Input Parameter:
2823: . prob - The PetscDS object

2825:   Output Parameter:
2826: . components - The number of components

2828:   Level: beginner

2830: .seealso: `PetscDSGetComponentOffsets()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2831: @*/
2832: PetscErrorCode PetscDSGetComponents(PetscDS prob, PetscInt *components[])
2833: {
2835:   PetscDSSetUp(prob);
2837:   *components = prob->Nc;
2838:   return 0;
2839: }

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

2844:   Not collective

2846:   Input Parameters:
2847: + prob - The PetscDS object
2848: - f - The field number

2850:   Output Parameter:
2851: . off - The offset

2853:   Level: beginner

2855: .seealso: `PetscDSGetNumFields()`, `PetscDSCreate()`
2856: @*/
2857: PetscErrorCode PetscDSGetComponentOffset(PetscDS prob, PetscInt f, PetscInt *off)
2858: {
2862:   PetscDSSetUp(prob);
2863:   *off = prob->off[f];
2864:   return 0;
2865: }

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

2870:   Not collective

2872:   Input Parameter:
2873: . prob - The PetscDS object

2875:   Output Parameter:
2876: . offsets - The offsets

2878:   Level: beginner

2880: .seealso: `PetscDSGetNumFields()`, `PetscDSCreate()`
2881: @*/
2882: PetscErrorCode PetscDSGetComponentOffsets(PetscDS prob, PetscInt *offsets[])
2883: {
2886:   PetscDSSetUp(prob);
2887:   *offsets = prob->off;
2888:   return 0;
2889: }

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

2894:   Not collective

2896:   Input Parameter:
2897: . prob - The PetscDS object

2899:   Output Parameter:
2900: . offsets - The offsets

2902:   Level: beginner

2904: .seealso: `PetscDSGetNumFields()`, `PetscDSCreate()`
2905: @*/
2906: PetscErrorCode PetscDSGetComponentDerivativeOffsets(PetscDS prob, PetscInt *offsets[])
2907: {
2910:   PetscDSSetUp(prob);
2911:   *offsets = prob->offDer;
2912:   return 0;
2913: }

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

2918:   Not collective

2920:   Input Parameters:
2921: + ds - The PetscDS object
2922: - s  - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive

2924:   Output Parameter:
2925: . offsets - The offsets

2927:   Level: beginner

2929: .seealso: `PetscDSGetNumFields()`, `PetscDSCreate()`
2930: @*/
2931: PetscErrorCode PetscDSGetComponentOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[])
2932: {
2937:   PetscDSSetUp(ds);
2938:   *offsets = ds->offCohesive[s];
2939:   return 0;
2940: }

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

2945:   Not collective

2947:   Input Parameters:
2948: + ds - The PetscDS object
2949: - s  - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive

2951:   Output Parameter:
2952: . offsets - The offsets

2954:   Level: beginner

2956: .seealso: `PetscDSGetNumFields()`, `PetscDSCreate()`
2957: @*/
2958: PetscErrorCode PetscDSGetComponentDerivativeOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[])
2959: {
2964:   PetscDSSetUp(ds);
2965:   *offsets = ds->offDerCohesive[s];
2966:   return 0;
2967: }

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

2972:   Not collective

2974:   Input Parameter:
2975: . prob - The PetscDS object

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

2980:   Level: intermediate

2982: .seealso: `PetscDSCreate()`
2983: @*/
2984: PetscErrorCode PetscDSGetTabulation(PetscDS prob, PetscTabulation *T[])
2985: {
2988:   PetscDSSetUp(prob);
2989:   *T = prob->T;
2990:   return 0;
2991: }

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

2996:   Not collective

2998:   Input Parameter:
2999: . prob - The PetscDS object

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

3004:   Level: intermediate

3006: .seealso: `PetscDSGetTabulation()`, `PetscDSCreate()`
3007: @*/
3008: PetscErrorCode PetscDSGetFaceTabulation(PetscDS prob, PetscTabulation *Tf[])
3009: {
3012:   PetscDSSetUp(prob);
3013:   *Tf = prob->Tf;
3014:   return 0;
3015: }

3017: PetscErrorCode PetscDSGetEvaluationArrays(PetscDS prob, PetscScalar **u, PetscScalar **u_t, PetscScalar **u_x)
3018: {
3020:   PetscDSSetUp(prob);
3021:   if (u) {
3023:     *u = prob->u;
3024:   }
3025:   if (u_t) {
3027:     *u_t = prob->u_t;
3028:   }
3029:   if (u_x) {
3031:     *u_x = prob->u_x;
3032:   }
3033:   return 0;
3034: }

3036: PetscErrorCode PetscDSGetWeakFormArrays(PetscDS prob, PetscScalar **f0, PetscScalar **f1, PetscScalar **g0, PetscScalar **g1, PetscScalar **g2, PetscScalar **g3)
3037: {
3039:   PetscDSSetUp(prob);
3040:   if (f0) {
3042:     *f0 = prob->f0;
3043:   }
3044:   if (f1) {
3046:     *f1 = prob->f1;
3047:   }
3048:   if (g0) {
3050:     *g0 = prob->g0;
3051:   }
3052:   if (g1) {
3054:     *g1 = prob->g1;
3055:   }
3056:   if (g2) {
3058:     *g2 = prob->g2;
3059:   }
3060:   if (g3) {
3062:     *g3 = prob->g3;
3063:   }
3064:   return 0;
3065: }

3067: PetscErrorCode PetscDSGetWorkspace(PetscDS prob, PetscReal **x, PetscScalar **basisReal, PetscScalar **basisDerReal, PetscScalar **testReal, PetscScalar **testDerReal)
3068: {
3070:   PetscDSSetUp(prob);
3071:   if (x) {
3073:     *x = prob->x;
3074:   }
3075:   if (basisReal) {
3077:     *basisReal = prob->basisReal;
3078:   }
3079:   if (basisDerReal) {
3081:     *basisDerReal = prob->basisDerReal;
3082:   }
3083:   if (testReal) {
3085:     *testReal = prob->testReal;
3086:   }
3087:   if (testDerReal) {
3089:     *testDerReal = prob->testDerReal;
3090:   }
3091:   return 0;
3092: }

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

3097:   Collective on ds

3099:   Input Parameters:
3100: + ds       - The PetscDS object
3101: . type     - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
3102: . name     - The BC name
3103: . label    - The label defining constrained points
3104: . Nv       - The number of DMLabel values for constrained points
3105: . values   - An array of label values for constrained points
3106: . field    - The field to constrain
3107: . Nc       - The number of constrained field components (0 will constrain all fields)
3108: . comps    - An array of constrained component numbers
3109: . bcFunc   - A pointwise function giving boundary values
3110: . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL
3111: - ctx      - An optional user context for bcFunc

3113:   Output Parameters:
3114: - bd       - The boundary number

3116:   Options Database Keys:
3117: + -bc_<boundary name> <num> - Overrides the boundary ids
3118: - -bc_<boundary name>_comp <num> - Overrides the boundary components

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

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

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

3127: $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
3128: $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
3129: $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
3130: $        PetscReal time, const PetscReal x[], PetscScalar bcval[])

3132: + dim - the spatial dimension
3133: . Nf - the number of fields
3134: . uOff - the offset into u[] and u_t[] for each field
3135: . uOff_x - the offset into u_x[] for each field
3136: . u - each field evaluated at the current point
3137: . u_t - the time derivative of each field evaluated at the current point
3138: . u_x - the gradient of each field evaluated at the current point
3139: . aOff - the offset into a[] and a_t[] for each auxiliary field
3140: . aOff_x - the offset into a_x[] for each auxiliary field
3141: . a - each auxiliary field evaluated at the current point
3142: . a_t - the time derivative of each auxiliary field evaluated at the current point
3143: . a_x - the gradient of auxiliary each field evaluated at the current point
3144: . t - current time
3145: . x - coordinates of the current point
3146: . numConstants - number of constant parameters
3147: . constants - constant parameters
3148: - bcval - output values at the current point

3150:   Level: developer

3152: .seealso: `PetscDSAddBoundaryByName()`, `PetscDSGetBoundary()`, `PetscDSSetResidual()`, `PetscDSSetBdResidual()`
3153: @*/
3154: PetscErrorCode PetscDSAddBoundary(PetscDS ds, DMBoundaryConditionType type, const char name[], DMLabel label, PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx, PetscInt *bd)
3155: {
3156:   DSBoundary  head = ds->boundary, b;
3157:   PetscInt    n    = 0;
3158:   const char *lname;

3167:   if (Nc > 0) {
3168:     PetscInt *fcomps;
3169:     PetscInt  c;

3171:     PetscDSGetComponents(ds, &fcomps);
3173:     for (c = 0; c < Nc; ++c) {
3175:     }
3176:   }
3177:   PetscNew(&b);
3178:   PetscStrallocpy(name, (char **)&b->name);
3179:   PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf);
3180:   PetscWeakFormSetNumFields(b->wf, ds->Nf);
3181:   PetscMalloc1(Nv, &b->values);
3182:   if (Nv) PetscArraycpy(b->values, values, Nv);
3183:   PetscMalloc1(Nc, &b->comps);
3184:   if (Nc) PetscArraycpy(b->comps, comps, Nc);
3185:   PetscObjectGetName((PetscObject)label, &lname);
3186:   PetscStrallocpy(lname, (char **)&b->lname);
3187:   b->type   = type;
3188:   b->label  = label;
3189:   b->Nv     = Nv;
3190:   b->field  = field;
3191:   b->Nc     = Nc;
3192:   b->func   = bcFunc;
3193:   b->func_t = bcFunc_t;
3194:   b->ctx    = ctx;
3195:   b->next   = NULL;
3196:   /* Append to linked list so that we can preserve the order */
3197:   if (!head) ds->boundary = b;
3198:   while (head) {
3199:     if (!head->next) {
3200:       head->next = b;
3201:       head       = b;
3202:     }
3203:     head = head->next;
3204:     ++n;
3205:   }
3206:   if (bd) {
3208:     *bd = n;
3209:   }
3210:   return 0;
3211: }

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

3216:   Collective on ds

3218:   Input Parameters:
3219: + ds       - The PetscDS object
3220: . type     - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
3221: . name     - The BC name
3222: . lname    - The naem of the label defining constrained points
3223: . Nv       - The number of DMLabel values for constrained points
3224: . values   - An array of label values for constrained points
3225: . field    - The field to constrain
3226: . Nc       - The number of constrained field components (0 will constrain all fields)
3227: . comps    - An array of constrained component numbers
3228: . bcFunc   - A pointwise function giving boundary values
3229: . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL
3230: - ctx      - An optional user context for bcFunc

3232:   Output Parameters:
3233: - bd       - The boundary number

3235:   Options Database Keys:
3236: + -bc_<boundary name> <num> - Overrides the boundary ids
3237: - -bc_<boundary name>_comp <num> - Overrides the boundary components

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

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

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

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

3248: $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
3249: $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
3250: $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
3251: $        PetscReal time, const PetscReal x[], PetscScalar bcval[])

3253: + dim - the spatial dimension
3254: . Nf - the number of fields
3255: . uOff - the offset into u[] and u_t[] for each field
3256: . uOff_x - the offset into u_x[] for each field
3257: . u - each field evaluated at the current point
3258: . u_t - the time derivative of each field evaluated at the current point
3259: . u_x - the gradient of each field evaluated at the current point
3260: . aOff - the offset into a[] and a_t[] for each auxiliary field
3261: . aOff_x - the offset into a_x[] for each auxiliary field
3262: . a - each auxiliary field evaluated at the current point
3263: . a_t - the time derivative of each auxiliary field evaluated at the current point
3264: . a_x - the gradient of auxiliary each field evaluated at the current point
3265: . t - current time
3266: . x - coordinates of the current point
3267: . numConstants - number of constant parameters
3268: . constants - constant parameters
3269: - bcval - output values at the current point

3271:   Level: developer

3273: .seealso: `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSSetResidual()`, `PetscDSSetBdResidual()`
3274: @*/
3275: PetscErrorCode PetscDSAddBoundaryByName(PetscDS ds, DMBoundaryConditionType type, const char name[], const char lname[], PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx, PetscInt *bd)
3276: {
3277:   DSBoundary head = ds->boundary, b;
3278:   PetscInt   n    = 0;

3287:   PetscNew(&b);
3288:   PetscStrallocpy(name, (char **)&b->name);
3289:   PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf);
3290:   PetscWeakFormSetNumFields(b->wf, ds->Nf);
3291:   PetscMalloc1(Nv, &b->values);
3292:   if (Nv) PetscArraycpy(b->values, values, Nv);
3293:   PetscMalloc1(Nc, &b->comps);
3294:   if (Nc) PetscArraycpy(b->comps, comps, Nc);
3295:   PetscStrallocpy(lname, (char **)&b->lname);
3296:   b->type   = type;
3297:   b->label  = NULL;
3298:   b->Nv     = Nv;
3299:   b->field  = field;
3300:   b->Nc     = Nc;
3301:   b->func   = bcFunc;
3302:   b->func_t = bcFunc_t;
3303:   b->ctx    = ctx;
3304:   b->next   = NULL;
3305:   /* Append to linked list so that we can preserve the order */
3306:   if (!head) ds->boundary = b;
3307:   while (head) {
3308:     if (!head->next) {
3309:       head->next = b;
3310:       head       = b;
3311:     }
3312:     head = head->next;
3313:     ++n;
3314:   }
3315:   if (bd) {
3317:     *bd = n;
3318:   }
3319:   return 0;
3320: }

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

3325:   Input Parameters:
3326: + ds       - The PetscDS object
3327: . bd       - The boundary condition number
3328: . type     - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
3329: . name     - The BC name
3330: . label    - The label defining constrained points
3331: . Nv       - The number of DMLabel ids for constrained points
3332: . values   - An array of ids for constrained points
3333: . field    - The field to constrain
3334: . Nc       - The number of constrained field components
3335: . comps    - An array of constrained component numbers
3336: . bcFunc   - A pointwise function giving boundary values
3337: . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL
3338: - ctx      - An optional user context for bcFunc

3340:   Note:
3341:   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.

3343:   Level: developer

3345: .seealso: `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSGetNumBoundary()`
3346: @*/
3347: PetscErrorCode PetscDSUpdateBoundary(PetscDS ds, PetscInt bd, DMBoundaryConditionType type, const char name[], DMLabel label, PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx)
3348: {
3349:   DSBoundary b = ds->boundary;
3350:   PetscInt   n = 0;

3353:   while (b) {
3354:     if (n == bd) break;
3355:     b = b->next;
3356:     ++n;
3357:   }
3359:   if (name) {
3360:     PetscFree(b->name);
3361:     PetscStrallocpy(name, (char **)&b->name);
3362:   }
3363:   b->type = type;
3364:   if (label) {
3365:     const char *name;

3367:     b->label = label;
3368:     PetscFree(b->lname);
3369:     PetscObjectGetName((PetscObject)label, &name);
3370:     PetscStrallocpy(name, (char **)&b->lname);
3371:   }
3372:   if (Nv >= 0) {
3373:     b->Nv = Nv;
3374:     PetscFree(b->values);
3375:     PetscMalloc1(Nv, &b->values);
3376:     if (Nv) PetscArraycpy(b->values, values, Nv);
3377:   }
3378:   if (field >= 0) b->field = field;
3379:   if (Nc >= 0) {
3380:     b->Nc = Nc;
3381:     PetscFree(b->comps);
3382:     PetscMalloc1(Nc, &b->comps);
3383:     if (Nc) PetscArraycpy(b->comps, comps, Nc);
3384:   }
3385:   if (bcFunc) b->func = bcFunc;
3386:   if (bcFunc_t) b->func_t = bcFunc_t;
3387:   if (ctx) b->ctx = ctx;
3388:   return 0;
3389: }

3391: /*@
3392:   PetscDSGetNumBoundary - Get the number of registered BC

3394:   Input Parameters:
3395: . ds - The PetscDS object

3397:   Output Parameters:
3398: . numBd - The number of BC

3400:   Level: intermediate

3402: .seealso: `PetscDSAddBoundary()`, `PetscDSGetBoundary()`
3403: @*/
3404: PetscErrorCode PetscDSGetNumBoundary(PetscDS ds, PetscInt *numBd)
3405: {
3406:   DSBoundary b = ds->boundary;

3410:   *numBd = 0;
3411:   while (b) {
3412:     ++(*numBd);
3413:     b = b->next;
3414:   }
3415:   return 0;
3416: }

3418: /*@C
3419:   PetscDSGetBoundary - Gets a boundary condition to the model

3421:   Input Parameters:
3422: + ds          - The PetscDS object
3423: - bd          - The BC number

3425:   Output Parameters:
3426: + wf       - The PetscWeakForm holding the pointwise functions
3427: . type     - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
3428: . name     - The BC name
3429: . label    - The label defining constrained points
3430: . Nv       - The number of DMLabel ids for constrained points
3431: . values   - An array of ids for constrained points
3432: . field    - The field to constrain
3433: . Nc       - The number of constrained field components
3434: . comps    - An array of constrained component numbers
3435: . bcFunc   - A pointwise function giving boundary values
3436: . bcFunc_t - A pointwise function giving the time derivative of the boundary values
3437: - ctx      - An optional user context for bcFunc

3439:   Options Database Keys:
3440: + -bc_<boundary name> <num> - Overrides the boundary ids
3441: - -bc_<boundary name>_comp <num> - Overrides the boundary components

3443:   Level: developer

3445: .seealso: `PetscDSAddBoundary()`
3446: @*/
3447: PetscErrorCode PetscDSGetBoundary(PetscDS ds, PetscInt bd, PetscWeakForm *wf, DMBoundaryConditionType *type, const char *name[], DMLabel *label, PetscInt *Nv, const PetscInt *values[], PetscInt *field, PetscInt *Nc, const PetscInt *comps[], void (**func)(void), void (**func_t)(void), void **ctx)
3448: {
3449:   DSBoundary b = ds->boundary;
3450:   PetscInt   n = 0;

3453:   while (b) {
3454:     if (n == bd) break;
3455:     b = b->next;
3456:     ++n;
3457:   }
3459:   if (wf) {
3461:     *wf = b->wf;
3462:   }
3463:   if (type) {
3465:     *type = b->type;
3466:   }
3467:   if (name) {
3469:     *name = b->name;
3470:   }
3471:   if (label) {
3473:     *label = b->label;
3474:   }
3475:   if (Nv) {
3477:     *Nv = b->Nv;
3478:   }
3479:   if (values) {
3481:     *values = b->values;
3482:   }
3483:   if (field) {
3485:     *field = b->field;
3486:   }
3487:   if (Nc) {
3489:     *Nc = b->Nc;
3490:   }
3491:   if (comps) {
3493:     *comps = b->comps;
3494:   }
3495:   if (func) {
3497:     *func = b->func;
3498:   }
3499:   if (func_t) {
3501:     *func_t = b->func_t;
3502:   }
3503:   if (ctx) {
3505:     *ctx = b->ctx;
3506:   }
3507:   return 0;
3508: }

3510: static PetscErrorCode DSBoundaryDuplicate_Internal(DSBoundary b, DSBoundary *bNew)
3511: {
3512:   PetscNew(bNew);
3513:   PetscWeakFormCreate(PETSC_COMM_SELF, &(*bNew)->wf);
3514:   PetscWeakFormCopy(b->wf, (*bNew)->wf);
3515:   PetscStrallocpy(b->name, (char **)&((*bNew)->name));
3516:   PetscStrallocpy(b->lname, (char **)&((*bNew)->lname));
3517:   (*bNew)->type  = b->type;
3518:   (*bNew)->label = b->label;
3519:   (*bNew)->Nv    = b->Nv;
3520:   PetscMalloc1(b->Nv, &(*bNew)->values);
3521:   PetscArraycpy((*bNew)->values, b->values, b->Nv);
3522:   (*bNew)->field = b->field;
3523:   (*bNew)->Nc    = b->Nc;
3524:   PetscMalloc1(b->Nc, &(*bNew)->comps);
3525:   PetscArraycpy((*bNew)->comps, b->comps, b->Nc);
3526:   (*bNew)->func   = b->func;
3527:   (*bNew)->func_t = b->func_t;
3528:   (*bNew)->ctx    = b->ctx;
3529:   return 0;
3530: }

3532: /*@
3533:   PetscDSCopyBoundary - Copy all boundary condition objects to the new problem

3535:   Not collective

3537:   Input Parameters:
3538: + ds        - The source PetscDS object
3539: . numFields - The number of selected fields, or PETSC_DEFAULT for all fields
3540: - fields    - The selected fields, or NULL for all fields

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

3545:   Level: intermediate

3547: .seealso: `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3548: @*/
3549: PetscErrorCode PetscDSCopyBoundary(PetscDS ds, PetscInt numFields, const PetscInt fields[], PetscDS newds)
3550: {
3551:   DSBoundary b, *lastnext;

3555:   if (ds == newds) return 0;
3556:   PetscDSDestroyBoundary(newds);
3557:   lastnext = &(newds->boundary);
3558:   for (b = ds->boundary; b; b = b->next) {
3559:     DSBoundary bNew;
3560:     PetscInt   fieldNew = -1;

3562:     if (numFields > 0 && fields) {
3563:       PetscInt f;

3565:       for (f = 0; f < numFields; ++f)
3566:         if (b->field == fields[f]) break;
3567:       if (f == numFields) continue;
3568:       fieldNew = f;
3569:     }
3570:     DSBoundaryDuplicate_Internal(b, &bNew);
3571:     bNew->field = fieldNew < 0 ? b->field : fieldNew;
3572:     *lastnext   = bNew;
3573:     lastnext    = &(bNew->next);
3574:   }
3575:   return 0;
3576: }

3578: /*@
3579:   PetscDSDestroyBoundary - Remove all DMBoundary objects from the PetscDS

3581:   Not collective

3583:   Input Parameter:
3584: . ds - The PetscDS object

3586:   Level: intermediate

3588: .seealso: `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`
3589: @*/
3590: PetscErrorCode PetscDSDestroyBoundary(PetscDS ds)
3591: {
3592:   DSBoundary next = ds->boundary;

3594:   while (next) {
3595:     DSBoundary b = next;

3597:     next = b->next;
3598:     PetscWeakFormDestroy(&b->wf);
3599:     PetscFree(b->name);
3600:     PetscFree(b->lname);
3601:     PetscFree(b->values);
3602:     PetscFree(b->comps);
3603:     PetscFree(b);
3604:   }
3605:   return 0;
3606: }

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

3611:   Not collective

3613:   Input Parameters:
3614: + prob - The PetscDS object
3615: . numFields - Number of new fields
3616: - fields - Old field number for each new field

3618:   Output Parameter:
3619: . newprob - The PetscDS copy

3621:   Level: intermediate

3623: .seealso: `PetscDSSelectEquations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3624: @*/
3625: PetscErrorCode PetscDSSelectDiscretizations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob)
3626: {
3627:   PetscInt Nf, Nfn, fn;

3632:   PetscDSGetNumFields(prob, &Nf);
3633:   PetscDSGetNumFields(newprob, &Nfn);
3634:   numFields = numFields < 0 ? Nf : numFields;
3635:   for (fn = 0; fn < numFields; ++fn) {
3636:     const PetscInt f = fields ? fields[fn] : fn;
3637:     PetscObject    disc;

3639:     if (f >= Nf) continue;
3640:     PetscDSGetDiscretization(prob, f, &disc);
3641:     PetscDSSetDiscretization(newprob, fn, disc);
3642:   }
3643:   return 0;
3644: }

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

3649:   Not collective

3651:   Input Parameters:
3652: + prob - The PetscDS object
3653: . numFields - Number of new fields
3654: - fields - Old field number for each new field

3656:   Output Parameter:
3657: . newprob - The PetscDS copy

3659:   Level: intermediate

3661: .seealso: `PetscDSSelectDiscretizations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3662: @*/
3663: PetscErrorCode PetscDSSelectEquations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob)
3664: {
3665:   PetscInt Nf, Nfn, fn, gn;

3670:   PetscDSGetNumFields(prob, &Nf);
3671:   PetscDSGetNumFields(newprob, &Nfn);
3673:   for (fn = 0; fn < numFields; ++fn) {
3674:     const PetscInt   f = fields ? fields[fn] : fn;
3675:     PetscPointFunc   obj;
3676:     PetscPointFunc   f0, f1;
3677:     PetscBdPointFunc f0Bd, f1Bd;
3678:     PetscRiemannFunc r;

3680:     if (f >= Nf) continue;
3681:     PetscDSGetObjective(prob, f, &obj);
3682:     PetscDSGetResidual(prob, f, &f0, &f1);
3683:     PetscDSGetBdResidual(prob, f, &f0Bd, &f1Bd);
3684:     PetscDSGetRiemannSolver(prob, f, &r);
3685:     PetscDSSetObjective(newprob, fn, obj);
3686:     PetscDSSetResidual(newprob, fn, f0, f1);
3687:     PetscDSSetBdResidual(newprob, fn, f0Bd, f1Bd);
3688:     PetscDSSetRiemannSolver(newprob, fn, r);
3689:     for (gn = 0; gn < numFields; ++gn) {
3690:       const PetscInt  g = fields ? fields[gn] : gn;
3691:       PetscPointJac   g0, g1, g2, g3;
3692:       PetscPointJac   g0p, g1p, g2p, g3p;
3693:       PetscBdPointJac g0Bd, g1Bd, g2Bd, g3Bd;

3695:       if (g >= Nf) continue;
3696:       PetscDSGetJacobian(prob, f, g, &g0, &g1, &g2, &g3);
3697:       PetscDSGetJacobianPreconditioner(prob, f, g, &g0p, &g1p, &g2p, &g3p);
3698:       PetscDSGetBdJacobian(prob, f, g, &g0Bd, &g1Bd, &g2Bd, &g3Bd);
3699:       PetscDSSetJacobian(newprob, fn, gn, g0, g1, g2, g3);
3700:       PetscDSSetJacobianPreconditioner(newprob, fn, gn, g0p, g1p, g2p, g3p);
3701:       PetscDSSetBdJacobian(newprob, fn, gn, g0Bd, g1Bd, g2Bd, g3Bd);
3702:     }
3703:   }
3704:   return 0;
3705: }

3707: /*@
3708:   PetscDSCopyEquations - Copy all pointwise function pointers to the new problem

3710:   Not collective

3712:   Input Parameter:
3713: . prob - The PetscDS object

3715:   Output Parameter:
3716: . newprob - The PetscDS copy

3718:   Level: intermediate

3720: .seealso: `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3721: @*/
3722: PetscErrorCode PetscDSCopyEquations(PetscDS prob, PetscDS newprob)
3723: {
3724:   PetscWeakForm wf, newwf;
3725:   PetscInt      Nf, Ng;

3729:   PetscDSGetNumFields(prob, &Nf);
3730:   PetscDSGetNumFields(newprob, &Ng);
3732:   PetscDSGetWeakForm(prob, &wf);
3733:   PetscDSGetWeakForm(newprob, &newwf);
3734:   PetscWeakFormCopy(wf, newwf);
3735:   return 0;
3736: }

3738: /*@
3739:   PetscDSCopyConstants - Copy all constants to the new problem

3741:   Not collective

3743:   Input Parameter:
3744: . prob - The PetscDS object

3746:   Output Parameter:
3747: . newprob - The PetscDS copy

3749:   Level: intermediate

3751: .seealso: `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3752: @*/
3753: PetscErrorCode PetscDSCopyConstants(PetscDS prob, PetscDS newprob)
3754: {
3755:   PetscInt           Nc;
3756:   const PetscScalar *constants;

3760:   PetscDSGetConstants(prob, &Nc, &constants);
3761:   PetscDSSetConstants(newprob, Nc, (PetscScalar *)constants);
3762:   return 0;
3763: }

3765: /*@
3766:   PetscDSCopyExactSolutions - Copy all exact solutions to the new problem

3768:   Not collective

3770:   Input Parameter:
3771: . ds - The PetscDS object

3773:   Output Parameter:
3774: . newds - The PetscDS copy

3776:   Level: intermediate

3778: .seealso: `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3779: @*/
3780: PetscErrorCode PetscDSCopyExactSolutions(PetscDS ds, PetscDS newds)
3781: {
3782:   PetscSimplePointFunc sol;
3783:   void                *ctx;
3784:   PetscInt             Nf, f;

3788:   PetscDSGetNumFields(ds, &Nf);
3789:   for (f = 0; f < Nf; ++f) {
3790:     PetscDSGetExactSolution(ds, f, &sol, &ctx);
3791:     PetscDSSetExactSolution(newds, f, sol, ctx);
3792:     PetscDSGetExactSolutionTimeDerivative(ds, f, &sol, &ctx);
3793:     PetscDSSetExactSolutionTimeDerivative(newds, f, sol, ctx);
3794:   }
3795:   return 0;
3796: }

3798: PetscErrorCode PetscDSGetHeightSubspace(PetscDS prob, PetscInt height, PetscDS *subprob)
3799: {
3800:   PetscInt dim, Nf, f;

3804:   if (height == 0) {
3805:     *subprob = prob;
3806:     return 0;
3807:   }
3808:   PetscDSGetNumFields(prob, &Nf);
3809:   PetscDSGetSpatialDimension(prob, &dim);
3811:   if (!prob->subprobs) PetscCalloc1(dim, &prob->subprobs);
3812:   if (!prob->subprobs[height - 1]) {
3813:     PetscInt cdim;

3815:     PetscDSCreate(PetscObjectComm((PetscObject)prob), &prob->subprobs[height - 1]);
3816:     PetscDSGetCoordinateDimension(prob, &cdim);
3817:     PetscDSSetCoordinateDimension(prob->subprobs[height - 1], cdim);
3818:     for (f = 0; f < Nf; ++f) {
3819:       PetscFE      subfe;
3820:       PetscObject  obj;
3821:       PetscClassId id;

3823:       PetscDSGetDiscretization(prob, f, &obj);
3824:       PetscObjectGetClassId(obj, &id);
3825:       if (id == PETSCFE_CLASSID) PetscFEGetHeightSubspace((PetscFE)obj, height, &subfe);
3826:       else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unsupported discretization type for field %" PetscInt_FMT, f);
3827:       PetscDSSetDiscretization(prob->subprobs[height - 1], f, (PetscObject)subfe);
3828:     }
3829:   }
3830:   *subprob = prob->subprobs[height - 1];
3831:   return 0;
3832: }

3834: PetscErrorCode PetscDSGetDiscType_Internal(PetscDS ds, PetscInt f, PetscDiscType *disctype)
3835: {
3836:   PetscObject  obj;
3837:   PetscClassId id;
3838:   PetscInt     Nf;

3842:   *disctype = PETSC_DISC_NONE;
3843:   PetscDSGetNumFields(ds, &Nf);
3845:   PetscDSGetDiscretization(ds, f, &obj);
3846:   if (obj) {
3847:     PetscObjectGetClassId(obj, &id);
3848:     if (id == PETSCFE_CLASSID) *disctype = PETSC_DISC_FE;
3849:     else *disctype = PETSC_DISC_FV;
3850:   }
3851:   return 0;
3852: }

3854: static PetscErrorCode PetscDSDestroy_Basic(PetscDS ds)
3855: {
3856:   PetscFree(ds->data);
3857:   return 0;
3858: }

3860: static PetscErrorCode PetscDSInitialize_Basic(PetscDS ds)
3861: {
3862:   ds->ops->setfromoptions = NULL;
3863:   ds->ops->setup          = NULL;
3864:   ds->ops->view           = NULL;
3865:   ds->ops->destroy        = PetscDSDestroy_Basic;
3866:   return 0;
3867: }

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

3872:   Level: intermediate

3874: .seealso: `PetscDSType`, `PetscDSCreate()`, `PetscDSSetType()`
3875: M*/

3877: PETSC_EXTERN PetscErrorCode PetscDSCreate_Basic(PetscDS ds)
3878: {
3879:   PetscDS_Basic *b;

3882:   PetscNew(&b);
3883:   ds->data = b;

3885:   PetscDSInitialize_Basic(ds);
3886:   return 0;
3887: }