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:   Sample usage:
 31: .vb
 32:     PetscDSRegister("my_ds", MyPetscDSCreate);
 33: .ve

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

 45:   Level: advanced

 47:   Note:
 48:   `PetscDSRegister()` may be called multiple times to add several user-defined `PetscDSs`

 50:   Fortran Note:
 51:   Not available from Fortran

 53: .seealso: `PetscDSType`, `PetscDS`, `PetscDSRegisterAll()`, `PetscDSRegisterDestroy()`
 54: @*/
 55: PetscErrorCode PetscDSRegister(const char sname[], PetscErrorCode (*function)(PetscDS))
 56: {
 57:   PetscFunctionBegin;
 58:   PetscCall(PetscFunctionListAdd(&PetscDSList, sname, function));
 59:   PetscFunctionReturn(PETSC_SUCCESS);
 60: }

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

 65:   Collective on prob

 67:   Input Parameters:
 68: + prob - The `PetscDS` object
 69: - name - The `PetscDSType`

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

 74:   Level: intermediate

 76:   Fortran Note:
 77:   Not available from Fortran

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

 86:   PetscFunctionBegin;
 88:   PetscCall(PetscObjectTypeCompare((PetscObject)prob, name, &match));
 89:   if (match) PetscFunctionReturn(PETSC_SUCCESS);

 91:   PetscCall(PetscDSRegisterAll());
 92:   PetscCall(PetscFunctionListFind(PetscDSList, name, &r));
 93:   PetscCheck(r, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDS type: %s", name);

 95:   PetscTryTypeMethod(prob, destroy);
 96:   prob->ops->destroy = NULL;

 98:   PetscCall((*r)(prob));
 99:   PetscCall(PetscObjectChangeTypeName((PetscObject)prob, name));
100:   PetscFunctionReturn(PETSC_SUCCESS);
101: }

103: /*@C
104:   PetscDSGetType - Gets the `PetscDSType` name (as a string) from the `PetscDS`

106:   Not Collective

108:   Input Parameter:
109: . prob  - The `PetscDS`

111:   Output Parameter:
112: . name - The `PetscDSType` name

114:   Level: intermediate

116:   Fortran Note:
117:   Not available from Fortran

119: .seealso: `PetscDSType`, `PetscDS`, `PetscDSSetType()`, `PetscDSCreate()`
120: @*/
121: PetscErrorCode PetscDSGetType(PetscDS prob, PetscDSType *name)
122: {
123:   PetscFunctionBegin;
126:   PetscCall(PetscDSRegisterAll());
127:   *name = ((PetscObject)prob)->type_name;
128:   PetscFunctionReturn(PETSC_SUCCESS);
129: }

131: static PetscErrorCode PetscDSView_Ascii(PetscDS ds, PetscViewer viewer)
132: {
133:   PetscViewerFormat  format;
134:   const PetscScalar *constants;
135:   PetscInt           Nf, numConstants, f;

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

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

182:     for (b = ds->boundary; b; b = b->next) {
183:       char    *name;
184:       PetscInt c, i;

186:       if (b->field != f) continue;
187:       PetscCall(PetscViewerASCIIPushTab(viewer));
188:       PetscCall(PetscViewerASCIIPrintf(viewer, "Boundary %s (%s) %s\n", b->name, b->lname, DMBoundaryConditionTypes[b->type]));
189:       if (!b->Nc) {
190:         PetscCall(PetscViewerASCIIPrintf(viewer, "  all components\n"));
191:       } else {
192:         PetscCall(PetscViewerASCIIPrintf(viewer, "  components: "));
193:         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
194:         for (c = 0; c < b->Nc; ++c) {
195:           if (c > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
196:           PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT, b->comps[c]));
197:         }
198:         PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
199:         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
200:       }
201:       PetscCall(PetscViewerASCIIPrintf(viewer, "  values: "));
202:       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
203:       for (i = 0; i < b->Nv; ++i) {
204:         if (i > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
205:         PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT, b->values[i]));
206:       }
207:       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
208:       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
209: #if defined(__clang__)
210:   #pragma clang diagnostic push
211:   #pragma clang diagnostic ignored "-Wformat-pedantic"
212: #elif defined(__GNUC__) || defined(__GNUG__)
213:   #pragma GCC diagnostic push
214:   #pragma GCC diagnostic ignored "-Wformat"
215: #endif
216:       if (b->func) {
217:         PetscCall(PetscDLAddr(b->func, &name));
218:         if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "  func: %s\n", name));
219:         else PetscCall(PetscViewerASCIIPrintf(viewer, "  func: %p\n", b->func));
220:         PetscCall(PetscFree(name));
221:       }
222:       if (b->func_t) {
223:         PetscCall(PetscDLAddr(b->func_t, &name));
224:         if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "  func_t: %s\n", name));
225:         else PetscCall(PetscViewerASCIIPrintf(viewer, "  func_t: %p\n", b->func_t));
226:         PetscCall(PetscFree(name));
227:       }
228: #if defined(__clang__)
229:   #pragma clang diagnostic pop
230: #elif defined(__GNUC__) || defined(__GNUG__)
231:   #pragma GCC diagnostic pop
232: #endif
233:       PetscCall(PetscWeakFormView(b->wf, viewer));
234:       PetscCall(PetscViewerASCIIPopTab(viewer));
235:     }
236:   }
237:   PetscCall(PetscDSGetConstants(ds, &numConstants, &constants));
238:   if (numConstants) {
239:     PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " constants\n", numConstants));
240:     PetscCall(PetscViewerASCIIPushTab(viewer));
241:     for (f = 0; f < numConstants; ++f) PetscCall(PetscViewerASCIIPrintf(viewer, "%g\n", (double)PetscRealPart(constants[f])));
242:     PetscCall(PetscViewerASCIIPopTab(viewer));
243:   }
244:   PetscCall(PetscWeakFormView(ds->wf, viewer));
245:   PetscCall(PetscViewerASCIIPopTab(viewer));
246:   PetscFunctionReturn(PETSC_SUCCESS);
247: }

249: /*@C
250:    PetscDSViewFromOptions - View a `PetscDS` based on values in the options database

252:    Collective on PetscDS

254:    Input Parameters:
255: +  A - the `PetscDS` object
256: .  obj - Optional object
257: -  name - command line option

259:    Level: intermediate

261: .seealso: `PetscDSType`, `PetscDS`, `PetscDSView()`, `PetscObjectViewFromOptions()`, `PetscDSCreate()`
262: @*/
263: PetscErrorCode PetscDSViewFromOptions(PetscDS A, PetscObject obj, const char name[])
264: {
265:   PetscFunctionBegin;
267:   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
268:   PetscFunctionReturn(PETSC_SUCCESS);
269: }

271: /*@C
272:   PetscDSView - Views a `PetscDS`

274:   Collective on prob

276:   Input Parameters:
277: + prob - the `PetscDS` object to view
278: - v  - the viewer

280:   Level: developer

282: .seealso: `PetscDSType`, `PetscDS`, `PetscViewer`, `PetscDSDestroy()`
283: @*/
284: PetscErrorCode PetscDSView(PetscDS prob, PetscViewer v)
285: {
286:   PetscBool iascii;

288:   PetscFunctionBegin;
290:   if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)prob), &v));
292:   PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii));
293:   if (iascii) PetscCall(PetscDSView_Ascii(prob, v));
294:   PetscTryTypeMethod(prob, view, v);
295:   PetscFunctionReturn(PETSC_SUCCESS);
296: }

298: /*@
299:   PetscDSSetFromOptions - sets parameters in a `PetscDS` from the options database

301:   Collective on prob

303:   Input Parameter:
304: . prob - the `PetscDS` object to set options for

306:   Options Database Keys:
307: + -petscds_type <type>     - Set the `PetscDS` type
308: . -petscds_view <view opt> - View the `PetscDS`
309: . -petscds_jac_pre         - Turn formation of a separate Jacobian preconditioner on or off
310: . -bc_<name> <ids>         - Specify a list of label ids for a boundary condition
311: - -bc_<name>_comp <comps>  - Specify a list of field components to constrain for a boundary condition

313:   Level: intermediate

315: .seealso: `PetscDS`, `PetscDSView()`
316: @*/
317: PetscErrorCode PetscDSSetFromOptions(PetscDS prob)
318: {
319:   DSBoundary  b;
320:   const char *defaultType;
321:   char        name[256];
322:   PetscBool   flg;

324:   PetscFunctionBegin;
326:   if (!((PetscObject)prob)->type_name) {
327:     defaultType = PETSCDSBASIC;
328:   } else {
329:     defaultType = ((PetscObject)prob)->type_name;
330:   }
331:   PetscCall(PetscDSRegisterAll());

333:   PetscObjectOptionsBegin((PetscObject)prob);
334:   for (b = prob->boundary; b; b = b->next) {
335:     char      optname[1024];
336:     PetscInt  ids[1024], len = 1024;
337:     PetscBool flg;

339:     PetscCall(PetscSNPrintf(optname, sizeof(optname), "-bc_%s", b->name));
340:     PetscCall(PetscMemzero(ids, sizeof(ids)));
341:     PetscCall(PetscOptionsIntArray(optname, "List of boundary IDs", "", ids, &len, &flg));
342:     if (flg) {
343:       b->Nv = len;
344:       PetscCall(PetscFree(b->values));
345:       PetscCall(PetscMalloc1(len, &b->values));
346:       PetscCall(PetscArraycpy(b->values, ids, len));
347:       PetscCall(PetscWeakFormRewriteKeys(b->wf, b->label, len, b->values));
348:     }
349:     len = 1024;
350:     PetscCall(PetscSNPrintf(optname, sizeof(optname), "-bc_%s_comp", b->name));
351:     PetscCall(PetscMemzero(ids, sizeof(ids)));
352:     PetscCall(PetscOptionsIntArray(optname, "List of boundary field components", "", ids, &len, &flg));
353:     if (flg) {
354:       b->Nc = len;
355:       PetscCall(PetscFree(b->comps));
356:       PetscCall(PetscMalloc1(len, &b->comps));
357:       PetscCall(PetscArraycpy(b->comps, ids, len));
358:     }
359:   }
360:   PetscCall(PetscOptionsFList("-petscds_type", "Discrete System", "PetscDSSetType", PetscDSList, defaultType, name, 256, &flg));
361:   if (flg) {
362:     PetscCall(PetscDSSetType(prob, name));
363:   } else if (!((PetscObject)prob)->type_name) {
364:     PetscCall(PetscDSSetType(prob, defaultType));
365:   }
366:   PetscCall(PetscOptionsBool("-petscds_jac_pre", "Discrete System", "PetscDSUseJacobianPreconditioner", prob->useJacPre, &prob->useJacPre, &flg));
367:   PetscTryTypeMethod(prob, setfromoptions);
368:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
369:   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)prob, PetscOptionsObject));
370:   PetscOptionsEnd();
371:   if (prob->Nf) PetscCall(PetscDSViewFromOptions(prob, NULL, "-petscds_view"));
372:   PetscFunctionReturn(PETSC_SUCCESS);
373: }

375: /*@C
376:   PetscDSSetUp - Construct data structures for the `PetscDS`

378:   Collective on prob

380:   Input Parameter:
381: . prob - the `PetscDS` object to setup

383:   Level: developer

385: .seealso: `PetscDS`, `PetscDSView()`, `PetscDSDestroy()`
386: @*/
387: PetscErrorCode PetscDSSetUp(PetscDS prob)
388: {
389:   const PetscInt Nf   = prob->Nf;
390:   PetscBool      hasH = PETSC_FALSE;
391:   PetscInt       dim, dimEmbed, NbMax = 0, NcMax = 0, NqMax = 0, NsMax = 1, f;

393:   PetscFunctionBegin;
395:   if (prob->setup) PetscFunctionReturn(PETSC_SUCCESS);
396:   /* Calculate sizes */
397:   PetscCall(PetscDSGetSpatialDimension(prob, &dim));
398:   PetscCall(PetscDSGetCoordinateDimension(prob, &dimEmbed));
399:   prob->totDim = prob->totComp = 0;
400:   PetscCall(PetscMalloc2(Nf, &prob->Nc, Nf, &prob->Nb));
401:   PetscCall(PetscCalloc2(Nf + 1, &prob->off, Nf + 1, &prob->offDer));
402:   PetscCall(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]));
403:   PetscCall(PetscMalloc2(Nf, &prob->T, Nf, &prob->Tf));
404:   for (f = 0; f < Nf; ++f) {
405:     PetscObject     obj;
406:     PetscClassId    id;
407:     PetscQuadrature q  = NULL;
408:     PetscInt        Nq = 0, Nb, Nc;

410:     PetscCall(PetscDSGetDiscretization(prob, f, &obj));
411:     if (prob->jetDegree[f] > 1) hasH = PETSC_TRUE;
412:     if (!obj) {
413:       /* Empty mesh */
414:       Nb = Nc    = 0;
415:       prob->T[f] = prob->Tf[f] = NULL;
416:     } else {
417:       PetscCall(PetscObjectGetClassId(obj, &id));
418:       if (id == PETSCFE_CLASSID) {
419:         PetscFE fe = (PetscFE)obj;

421:         PetscCall(PetscFEGetQuadrature(fe, &q));
422:         PetscCall(PetscFEGetDimension(fe, &Nb));
423:         PetscCall(PetscFEGetNumComponents(fe, &Nc));
424:         PetscCall(PetscFEGetCellTabulation(fe, prob->jetDegree[f], &prob->T[f]));
425:         PetscCall(PetscFEGetFaceTabulation(fe, prob->jetDegree[f], &prob->Tf[f]));
426:       } else if (id == PETSCFV_CLASSID) {
427:         PetscFV fv = (PetscFV)obj;

429:         PetscCall(PetscFVGetQuadrature(fv, &q));
430:         PetscCall(PetscFVGetNumComponents(fv, &Nc));
431:         Nb = Nc;
432:         PetscCall(PetscFVGetCellTabulation(fv, &prob->T[f]));
433:         /* TODO: should PetscFV also have face tabulation? Otherwise there will be a null pointer in prob->basisFace */
434:       } else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, f);
435:     }
436:     prob->Nc[f]                    = Nc;
437:     prob->Nb[f]                    = Nb;
438:     prob->off[f + 1]               = Nc + prob->off[f];
439:     prob->offDer[f + 1]            = Nc * dim + prob->offDer[f];
440:     prob->offCohesive[0][f + 1]    = (prob->cohesive[f] ? Nc : Nc * 2) + prob->offCohesive[0][f];
441:     prob->offDerCohesive[0][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) * dimEmbed + prob->offDerCohesive[0][f];
442:     prob->offCohesive[1][f]        = (prob->cohesive[f] ? 0 : Nc) + prob->offCohesive[0][f];
443:     prob->offDerCohesive[1][f]     = (prob->cohesive[f] ? 0 : Nc) * dimEmbed + prob->offDerCohesive[0][f];
444:     prob->offCohesive[2][f + 1]    = (prob->cohesive[f] ? Nc : Nc * 2) + prob->offCohesive[2][f];
445:     prob->offDerCohesive[2][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) * dimEmbed + prob->offDerCohesive[2][f];
446:     if (q) PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Nq, NULL, NULL));
447:     NqMax = PetscMax(NqMax, Nq);
448:     NbMax = PetscMax(NbMax, Nb);
449:     NcMax = PetscMax(NcMax, Nc);
450:     prob->totDim += Nb;
451:     prob->totComp += Nc;
452:     /* There are two faces for all fields on a cohesive cell, except for cohesive fields */
453:     if (prob->isCohesive && !prob->cohesive[f]) prob->totDim += Nb;
454:   }
455:   prob->offCohesive[1][Nf]    = prob->offCohesive[0][Nf];
456:   prob->offDerCohesive[1][Nf] = prob->offDerCohesive[0][Nf];
457:   /* Allocate works space */
458:   NsMax = 2; /* A non-cohesive discretizations can be used on a cohesive cell, so we need this extra workspace for all DS */
459:   PetscCall(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));
460:   PetscCall(PetscMalloc5(dimEmbed, &prob->x, NbMax * NcMax, &prob->basisReal, NbMax * NcMax * dimEmbed, &prob->basisDerReal, NbMax * NcMax, &prob->testReal, NbMax * NcMax * dimEmbed, &prob->testDerReal));
461:   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,
462:                          &prob->g2, NsMax * NsMax * NqMax * NcMax * NcMax * dimEmbed * dimEmbed, &prob->g3));
463:   PetscTryTypeMethod(prob, setup);
464:   prob->setup = PETSC_TRUE;
465:   PetscFunctionReturn(PETSC_SUCCESS);
466: }

468: static PetscErrorCode PetscDSDestroyStructs_Static(PetscDS prob)
469: {
470:   PetscFunctionBegin;
471:   PetscCall(PetscFree2(prob->Nc, prob->Nb));
472:   PetscCall(PetscFree2(prob->off, prob->offDer));
473:   PetscCall(PetscFree6(prob->offCohesive[0], prob->offCohesive[1], prob->offCohesive[2], prob->offDerCohesive[0], prob->offDerCohesive[1], prob->offDerCohesive[2]));
474:   PetscCall(PetscFree2(prob->T, prob->Tf));
475:   PetscCall(PetscFree3(prob->u, prob->u_t, prob->u_x));
476:   PetscCall(PetscFree5(prob->x, prob->basisReal, prob->basisDerReal, prob->testReal, prob->testDerReal));
477:   PetscCall(PetscFree6(prob->f0, prob->f1, prob->g0, prob->g1, prob->g2, prob->g3));
478:   PetscFunctionReturn(PETSC_SUCCESS);
479: }

481: static PetscErrorCode PetscDSEnlarge_Static(PetscDS prob, PetscInt NfNew)
482: {
483:   PetscObject          *tmpd;
484:   PetscBool            *tmpi;
485:   PetscInt             *tmpk;
486:   PetscBool            *tmpc;
487:   PetscPointFunc       *tmpup;
488:   PetscSimplePointFunc *tmpexactSol, *tmpexactSol_t;
489:   void                **tmpexactCtx, **tmpexactCtx_t;
490:   void                **tmpctx;
491:   PetscInt              Nf = prob->Nf, f;

493:   PetscFunctionBegin;
494:   if (Nf >= NfNew) PetscFunctionReturn(PETSC_SUCCESS);
495:   prob->setup = PETSC_FALSE;
496:   PetscCall(PetscDSDestroyStructs_Static(prob));
497:   PetscCall(PetscMalloc4(NfNew, &tmpd, NfNew, &tmpi, NfNew, &tmpc, NfNew, &tmpk));
498:   for (f = 0; f < Nf; ++f) {
499:     tmpd[f] = prob->disc[f];
500:     tmpi[f] = prob->implicit[f];
501:     tmpc[f] = prob->cohesive[f];
502:     tmpk[f] = prob->jetDegree[f];
503:   }
504:   for (f = Nf; f < NfNew; ++f) {
505:     tmpd[f] = NULL;
506:     tmpi[f] = PETSC_TRUE, tmpc[f] = PETSC_FALSE;
507:     tmpk[f] = 1;
508:   }
509:   PetscCall(PetscFree4(prob->disc, prob->implicit, prob->cohesive, prob->jetDegree));
510:   PetscCall(PetscWeakFormSetNumFields(prob->wf, NfNew));
511:   prob->Nf        = NfNew;
512:   prob->disc      = tmpd;
513:   prob->implicit  = tmpi;
514:   prob->cohesive  = tmpc;
515:   prob->jetDegree = tmpk;
516:   PetscCall(PetscCalloc2(NfNew, &tmpup, NfNew, &tmpctx));
517:   for (f = 0; f < Nf; ++f) tmpup[f] = prob->update[f];
518:   for (f = 0; f < Nf; ++f) tmpctx[f] = prob->ctx[f];
519:   for (f = Nf; f < NfNew; ++f) tmpup[f] = NULL;
520:   for (f = Nf; f < NfNew; ++f) tmpctx[f] = NULL;
521:   PetscCall(PetscFree2(prob->update, prob->ctx));
522:   prob->update = tmpup;
523:   prob->ctx    = tmpctx;
524:   PetscCall(PetscCalloc4(NfNew, &tmpexactSol, NfNew, &tmpexactCtx, NfNew, &tmpexactSol_t, NfNew, &tmpexactCtx_t));
525:   for (f = 0; f < Nf; ++f) tmpexactSol[f] = prob->exactSol[f];
526:   for (f = 0; f < Nf; ++f) tmpexactCtx[f] = prob->exactCtx[f];
527:   for (f = 0; f < Nf; ++f) tmpexactSol_t[f] = prob->exactSol_t[f];
528:   for (f = 0; f < Nf; ++f) tmpexactCtx_t[f] = prob->exactCtx_t[f];
529:   for (f = Nf; f < NfNew; ++f) tmpexactSol[f] = NULL;
530:   for (f = Nf; f < NfNew; ++f) tmpexactCtx[f] = NULL;
531:   for (f = Nf; f < NfNew; ++f) tmpexactSol_t[f] = NULL;
532:   for (f = Nf; f < NfNew; ++f) tmpexactCtx_t[f] = NULL;
533:   PetscCall(PetscFree4(prob->exactSol, prob->exactCtx, prob->exactSol_t, prob->exactCtx_t));
534:   prob->exactSol   = tmpexactSol;
535:   prob->exactCtx   = tmpexactCtx;
536:   prob->exactSol_t = tmpexactSol_t;
537:   prob->exactCtx_t = tmpexactCtx_t;
538:   PetscFunctionReturn(PETSC_SUCCESS);
539: }

541: /*@
542:   PetscDSDestroy - Destroys a PetscDS object

544:   Collective on prob

546:   Input Parameter:
547: . prob - the PetscDS object to destroy

549:   Level: developer

551: .seealso: `PetscDSView()`
552: @*/
553: PetscErrorCode PetscDSDestroy(PetscDS *ds)
554: {
555:   PetscInt f;

557:   PetscFunctionBegin;
558:   if (!*ds) PetscFunctionReturn(PETSC_SUCCESS);

561:   if (--((PetscObject)(*ds))->refct > 0) {
562:     *ds = NULL;
563:     PetscFunctionReturn(PETSC_SUCCESS);
564:   }
565:   ((PetscObject)(*ds))->refct = 0;
566:   if ((*ds)->subprobs) {
567:     PetscInt dim, d;

569:     PetscCall(PetscDSGetSpatialDimension(*ds, &dim));
570:     for (d = 0; d < dim; ++d) PetscCall(PetscDSDestroy(&(*ds)->subprobs[d]));
571:   }
572:   PetscCall(PetscFree((*ds)->subprobs));
573:   PetscCall(PetscDSDestroyStructs_Static(*ds));
574:   for (f = 0; f < (*ds)->Nf; ++f) PetscCall(PetscObjectDereference((*ds)->disc[f]));
575:   PetscCall(PetscFree4((*ds)->disc, (*ds)->implicit, (*ds)->cohesive, (*ds)->jetDegree));
576:   PetscCall(PetscWeakFormDestroy(&(*ds)->wf));
577:   PetscCall(PetscFree2((*ds)->update, (*ds)->ctx));
578:   PetscCall(PetscFree4((*ds)->exactSol, (*ds)->exactCtx, (*ds)->exactSol_t, (*ds)->exactCtx_t));
579:   PetscTryTypeMethod((*ds), destroy);
580:   PetscCall(PetscDSDestroyBoundary(*ds));
581:   PetscCall(PetscFree((*ds)->constants));
582:   PetscCall(PetscHeaderDestroy(ds));
583:   PetscFunctionReturn(PETSC_SUCCESS);
584: }

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

589:   Collective

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

594:   Output Parameter:
595: . ds   - The `PetscDS` object

597:   Level: beginner

599: .seealso: `PetscDS`, `PetscDSSetType()`, `PETSCDSBASIC`, `PetscDSType`
600: @*/
601: PetscErrorCode PetscDSCreate(MPI_Comm comm, PetscDS *ds)
602: {
603:   PetscDS p;

605:   PetscFunctionBegin;
607:   *ds = NULL;
608:   PetscCall(PetscDSInitializePackage());

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

612:   p->Nf           = 0;
613:   p->setup        = PETSC_FALSE;
614:   p->numConstants = 0;
615:   p->constants    = NULL;
616:   p->dimEmbed     = -1;
617:   p->useJacPre    = PETSC_TRUE;
618:   PetscCall(PetscWeakFormCreate(comm, &p->wf));

620:   *ds = p;
621:   PetscFunctionReturn(PETSC_SUCCESS);
622: }

624: /*@
625:   PetscDSGetNumFields - Returns the number of fields in the `PetscDS`

627:   Not collective

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

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

635:   Level: beginner

637: .seealso: `PetscDS`, `PetscDSGetSpatialDimension()`, `PetscDSCreate()`
638: @*/
639: PetscErrorCode PetscDSGetNumFields(PetscDS prob, PetscInt *Nf)
640: {
641:   PetscFunctionBegin;
644:   *Nf = prob->Nf;
645:   PetscFunctionReturn(PETSC_SUCCESS);
646: }

648: /*@
649:   PetscDSGetSpatialDimension - Returns the spatial dimension of the `PetscDS`, meaning the topological dimension of the discretizations

651:   Not collective

653:   Input Parameter:
654: . prob - The `PetscDS` object

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

659:   Level: beginner

661: .seealso: `PetscDS`, `PetscDSGetCoordinateDimension()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
662: @*/
663: PetscErrorCode PetscDSGetSpatialDimension(PetscDS prob, PetscInt *dim)
664: {
665:   PetscFunctionBegin;
668:   *dim = 0;
669:   if (prob->Nf) {
670:     PetscObject  obj;
671:     PetscClassId id;

673:     PetscCall(PetscDSGetDiscretization(prob, 0, &obj));
674:     if (obj) {
675:       PetscCall(PetscObjectGetClassId(obj, &id));
676:       if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetSpatialDimension((PetscFE)obj, dim));
677:       else if (id == PETSCFV_CLASSID) PetscCall(PetscFVGetSpatialDimension((PetscFV)obj, dim));
678:       else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
679:     }
680:   }
681:   PetscFunctionReturn(PETSC_SUCCESS);
682: }

684: /*@
685:   PetscDSGetCoordinateDimension - Returns the coordinate dimension of the `PetscDS`, meaning the dimension of the space into which the discretiaztions are embedded

687:   Not collective

689:   Input Parameter:
690: . prob - The `PetscDS` object

692:   Output Parameter:
693: . dimEmbed - The coordinate dimension

695:   Level: beginner

697: .seealso: `PetscDS`, `PetscDSSetCoordinateDimension()`, `PetscDSGetSpatialDimension()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
698: @*/
699: PetscErrorCode PetscDSGetCoordinateDimension(PetscDS prob, PetscInt *dimEmbed)
700: {
701:   PetscFunctionBegin;
704:   PetscCheck(prob->dimEmbed >= 0, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONGSTATE, "No coordinate dimension set for this DS");
705:   *dimEmbed = prob->dimEmbed;
706:   PetscFunctionReturn(PETSC_SUCCESS);
707: }

709: /*@
710:   PetscDSSetCoordinateDimension - Set the coordinate dimension of the `PetscDS`, meaning the dimension of the space into which the discretiaztions are embedded

712:   Logically collective on prob

714:   Input Parameters:
715: + prob - The `PetscDS` object
716: - dimEmbed - The coordinate dimension

718:   Level: beginner

720: .seealso: `PetscDS`, `PetscDSGetCoordinateDimension()`, `PetscDSGetSpatialDimension()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
721: @*/
722: PetscErrorCode PetscDSSetCoordinateDimension(PetscDS prob, PetscInt dimEmbed)
723: {
724:   PetscFunctionBegin;
726:   PetscCheck(dimEmbed >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate dimension must be non-negative, not %" PetscInt_FMT, dimEmbed);
727:   prob->dimEmbed = dimEmbed;
728:   PetscFunctionReturn(PETSC_SUCCESS);
729: }

731: /*@
732:   PetscDSIsCohesive - Returns the flag indicating that this `PetscDS` is for a cohesive cell

734:   Not collective

736:   Input Parameter:
737: . ds - The `PetscDS` object

739:   Output Parameter:
740: . isCohesive - The flag

742:   Level: developer

744: .seealso: `PetscDS`, `PetscDSGetNumCohesive()`, `PetscDSGetCohesive()`, `PetscDSSetCohesive()`, `PetscDSCreate()`
745: @*/
746: PetscErrorCode PetscDSIsCohesive(PetscDS ds, PetscBool *isCohesive)
747: {
748:   PetscFunctionBegin;
751:   *isCohesive = ds->isCohesive;
752:   PetscFunctionReturn(PETSC_SUCCESS);
753: }

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

758:   Not collective

760:   Input Parameter:
761: . ds - The `PetscDS` object

763:   Output Parameter:
764: . numCohesive - The number of cohesive fields

766:   Level: developer

768: .seealso: `PetscDS`, `PetscDSSetCohesive()`, `PetscDSCreate()`
769: @*/
770: PetscErrorCode PetscDSGetNumCohesive(PetscDS ds, PetscInt *numCohesive)
771: {
772:   PetscInt f;

774:   PetscFunctionBegin;
777:   *numCohesive = 0;
778:   for (f = 0; f < ds->Nf; ++f) *numCohesive += ds->cohesive[f] ? 1 : 0;
779:   PetscFunctionReturn(PETSC_SUCCESS);
780: }

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

785:   Not collective

787:   Input Parameters:
788: + ds - The `PetscDS` object
789: - f  - The field index

791:   Output Parameter:
792: . isCohesive - The flag

794:   Level: developer

796: .seealso: `PetscDS`, `PetscDSSetCohesive()`, `PetscDSIsCohesive()`, `PetscDSCreate()`
797: @*/
798: PetscErrorCode PetscDSGetCohesive(PetscDS ds, PetscInt f, PetscBool *isCohesive)
799: {
800:   PetscFunctionBegin;
803:   PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
804:   *isCohesive = ds->cohesive[f];
805:   PetscFunctionReturn(PETSC_SUCCESS);
806: }

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

811:   Not collective

813:   Input Parameters:
814: + ds - The `PetscDS` object
815: . f  - The field index
816: - isCohesive - The flag for a cohesive field

818:   Level: developer

820: .seealso: `PetscDS`, `PetscDSGetCohesive()`, `PetscDSIsCohesive()`, `PetscDSCreate()`
821: @*/
822: PetscErrorCode PetscDSSetCohesive(PetscDS ds, PetscInt f, PetscBool isCohesive)
823: {
824:   PetscInt i;

826:   PetscFunctionBegin;
828:   PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
829:   ds->cohesive[f] = isCohesive;
830:   ds->isCohesive  = PETSC_FALSE;
831:   for (i = 0; i < ds->Nf; ++i) ds->isCohesive = ds->isCohesive || ds->cohesive[f] ? PETSC_TRUE : PETSC_FALSE;
832:   PetscFunctionReturn(PETSC_SUCCESS);
833: }

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

838:   Not collective

840:   Input Parameter:
841: . prob - The `PetscDS` object

843:   Output Parameter:
844: . dim - The total problem dimension

846:   Level: beginner

848: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
849: @*/
850: PetscErrorCode PetscDSGetTotalDimension(PetscDS prob, PetscInt *dim)
851: {
852:   PetscFunctionBegin;
854:   PetscCall(PetscDSSetUp(prob));
856:   *dim = prob->totDim;
857:   PetscFunctionReturn(PETSC_SUCCESS);
858: }

860: /*@
861:   PetscDSGetTotalComponents - Returns the total number of components in this system

863:   Not collective

865:   Input Parameter:
866: . prob - The `PetscDS` object

868:   Output Parameter:
869: . dim - The total number of components

871:   Level: beginner

873: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
874: @*/
875: PetscErrorCode PetscDSGetTotalComponents(PetscDS prob, PetscInt *Nc)
876: {
877:   PetscFunctionBegin;
879:   PetscCall(PetscDSSetUp(prob));
881:   *Nc = prob->totComp;
882:   PetscFunctionReturn(PETSC_SUCCESS);
883: }

885: /*@
886:   PetscDSGetDiscretization - Returns the discretization object for the given field

888:   Not collective

890:   Input Parameters:
891: + prob - The `PetscDS` object
892: - f - The field number

894:   Output Parameter:
895: . disc - The discretization object

897:   Level: beginner

899: .seealso: `PetscDS`, `PetscFE`, `PetscFV`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
900: @*/
901: PetscErrorCode PetscDSGetDiscretization(PetscDS prob, PetscInt f, PetscObject *disc)
902: {
903:   PetscFunctionBeginHot;
906:   PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf);
907:   *disc = prob->disc[f];
908:   PetscFunctionReturn(PETSC_SUCCESS);
909: }

911: /*@
912:   PetscDSSetDiscretization - Sets the discretization object for the given field

914:   Not collective

916:   Input Parameters:
917: + prob - The `PetscDS` object
918: . f - The field number
919: - disc - The discretization object

921:   Level: beginner

923: .seealso: `PetscDS`, `PetscFE`, `PetscFV`, `PetscDSGetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
924: @*/
925: PetscErrorCode PetscDSSetDiscretization(PetscDS prob, PetscInt f, PetscObject disc)
926: {
927:   PetscFunctionBegin;
930:   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
931:   PetscCall(PetscDSEnlarge_Static(prob, f + 1));
932:   PetscCall(PetscObjectDereference(prob->disc[f]));
933:   prob->disc[f] = disc;
934:   PetscCall(PetscObjectReference(disc));
935:   if (disc) {
936:     PetscClassId id;

938:     PetscCall(PetscObjectGetClassId(disc, &id));
939:     if (id == PETSCFE_CLASSID) {
940:       PetscCall(PetscDSSetImplicit(prob, f, PETSC_TRUE));
941:     } else if (id == PETSCFV_CLASSID) {
942:       PetscCall(PetscDSSetImplicit(prob, f, PETSC_FALSE));
943:     }
944:     PetscCall(PetscDSSetJetDegree(prob, f, 1));
945:   }
946:   PetscFunctionReturn(PETSC_SUCCESS);
947: }

949: /*@
950:   PetscDSGetWeakForm - Returns the weak form object

952:   Not collective

954:   Input Parameter:
955: . ds - The `PetscDS` object

957:   Output Parameter:
958: . wf - The weak form object

960:   Level: beginner

962: .seealso: `PetscWeakForm`, `PetscDSSetWeakForm()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
963: @*/
964: PetscErrorCode PetscDSGetWeakForm(PetscDS ds, PetscWeakForm *wf)
965: {
966:   PetscFunctionBegin;
969:   *wf = ds->wf;
970:   PetscFunctionReturn(PETSC_SUCCESS);
971: }

973: /*@
974:   PetscDSSetWeakForm - Sets the weak form object

976:   Not collective

978:   Input Parameters:
979: + ds - The `PetscDS` object
980: - wf - The weak form object

982:   Level: beginner

984: .seealso: `PetscWeakForm`, `PetscDSGetWeakForm()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
985: @*/
986: PetscErrorCode PetscDSSetWeakForm(PetscDS ds, PetscWeakForm wf)
987: {
988:   PetscFunctionBegin;
991:   PetscCall(PetscObjectDereference((PetscObject)ds->wf));
992:   ds->wf = wf;
993:   PetscCall(PetscObjectReference((PetscObject)wf));
994:   PetscCall(PetscWeakFormSetNumFields(wf, ds->Nf));
995:   PetscFunctionReturn(PETSC_SUCCESS);
996: }

998: /*@
999:   PetscDSAddDiscretization - Adds a discretization object

1001:   Not collective

1003:   Input Parameters:
1004: + prob - The `PetscDS` object
1005: - disc - The boundary discretization object

1007:   Level: beginner

1009: .seealso: `PetscWeakForm`, `PetscDSGetDiscretization()`, `PetscDSSetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1010: @*/
1011: PetscErrorCode PetscDSAddDiscretization(PetscDS prob, PetscObject disc)
1012: {
1013:   PetscFunctionBegin;
1014:   PetscCall(PetscDSSetDiscretization(prob, prob->Nf, disc));
1015:   PetscFunctionReturn(PETSC_SUCCESS);
1016: }

1018: /*@
1019:   PetscDSGetQuadrature - Returns the quadrature, which must agree for all fields in the `PetscDS`

1021:   Not collective

1023:   Input Parameter:
1024: . prob - The `PetscDS` object

1026:   Output Parameter:
1027: . q - The quadrature object

1029:   Level: intermediate

1031: .seealso: `PetscDS`, `PetscQuadrature`, `PetscDSSetImplicit()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1032: @*/
1033: PetscErrorCode PetscDSGetQuadrature(PetscDS prob, PetscQuadrature *q)
1034: {
1035:   PetscObject  obj;
1036:   PetscClassId id;

1038:   PetscFunctionBegin;
1039:   *q = NULL;
1040:   if (!prob->Nf) PetscFunctionReturn(PETSC_SUCCESS);
1041:   PetscCall(PetscDSGetDiscretization(prob, 0, &obj));
1042:   PetscCall(PetscObjectGetClassId(obj, &id));
1043:   if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetQuadrature((PetscFE)obj, q));
1044:   else if (id == PETSCFV_CLASSID) PetscCall(PetscFVGetQuadrature((PetscFV)obj, q));
1045:   else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
1046:   PetscFunctionReturn(PETSC_SUCCESS);
1047: }

1049: /*@
1050:   PetscDSGetImplicit - Returns the flag for implicit solve for this field. This is just a guide for `TSIMEX`

1052:   Not collective

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

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

1061:   Level: developer

1063: .seealso: `TSIMEX`, `PetscDS`, `PetscDSSetImplicit()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1064: @*/
1065: PetscErrorCode PetscDSGetImplicit(PetscDS prob, PetscInt f, PetscBool *implicit)
1066: {
1067:   PetscFunctionBegin;
1070:   PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf);
1071:   *implicit = prob->implicit[f];
1072:   PetscFunctionReturn(PETSC_SUCCESS);
1073: }

1075: /*@
1076:   PetscDSSetImplicit - Set the flag for implicit solve for this field. This is just a guide for `TSIMEX`

1078:   Not collective

1080:   Input Parameters:
1081: + prob - The `PetscDS` object
1082: . f - The field number
1083: - implicit - The flag indicating what kind of solve to use for this field

1085:   Level: developer

1087: .seealso: `TSIMEX`, `PetscDSGetImplicit()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1088: @*/
1089: PetscErrorCode PetscDSSetImplicit(PetscDS prob, PetscInt f, PetscBool implicit)
1090: {
1091:   PetscFunctionBegin;
1093:   PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf);
1094:   prob->implicit[f] = implicit;
1095:   PetscFunctionReturn(PETSC_SUCCESS);
1096: }

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

1101:   Not collective

1103:   Input Parameters:
1104: + ds - The `PetscDS` object
1105: - f  - The field number

1107:   Output Parameter:
1108: . k  - The highest derivative we need to tabulate

1110:   Level: developer

1112: .seealso: `PetscDS`, `PetscDSSetJetDegree()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1113: @*/
1114: PetscErrorCode PetscDSGetJetDegree(PetscDS ds, PetscInt f, PetscInt *k)
1115: {
1116:   PetscFunctionBegin;
1119:   PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
1120:   *k = ds->jetDegree[f];
1121:   PetscFunctionReturn(PETSC_SUCCESS);
1122: }

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

1127:   Not collective

1129:   Input Parameters:
1130: + ds - The `PetscDS` object
1131: . f  - The field number
1132: - k  - The highest derivative we need to tabulate

1134:   Level: developer

1136: .seealso: ``PetscDS`, PetscDSGetJetDegree()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1137: @*/
1138: PetscErrorCode PetscDSSetJetDegree(PetscDS ds, PetscInt f, PetscInt k)
1139: {
1140:   PetscFunctionBegin;
1142:   PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
1143:   ds->jetDegree[f] = k;
1144:   PetscFunctionReturn(PETSC_SUCCESS);
1145: }

1147: 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[]))
1148: {
1149:   PetscPointFunc *tmp;
1150:   PetscInt        n;

1152:   PetscFunctionBegin;
1155:   PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
1156:   PetscCall(PetscWeakFormGetObjective(ds->wf, NULL, 0, f, 0, &n, &tmp));
1157:   *obj = tmp ? tmp[0] : NULL;
1158:   PetscFunctionReturn(PETSC_SUCCESS);
1159: }

1161: 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[]))
1162: {
1163:   PetscFunctionBegin;
1166:   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1167:   PetscCall(PetscWeakFormSetIndexObjective(ds->wf, NULL, 0, f, 0, 0, obj));
1168:   PetscFunctionReturn(PETSC_SUCCESS);
1169: }

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

1174:   Not collective

1176:   Input Parameters:
1177: + ds - The `PetscDS`
1178: - f  - The test field number

1180:   Output Parameters:
1181: + f0 - integrand for the test function term
1182: - f1 - integrand for the test function gradient term

1184:   Calling sequence for the callbacks f0 and f1:
1185: .vb
1186:   f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1187:      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1188:      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1189:      PetscReal t, const PetscReal x[], PetscScalar f0[])
1190: .ve
1191: + dim - the spatial dimension
1192: . Nf - the number of fields
1193: . uOff - the offset into u[] and u_t[] for each field
1194: . uOff_x - the offset into u_x[] for each field
1195: . u - each field evaluated at the current point
1196: . u_t - the time derivative of each field evaluated at the current point
1197: . u_x - the gradient of each field evaluated at the current point
1198: . aOff - the offset into a[] and a_t[] for each auxiliary field
1199: . aOff_x - the offset into a_x[] for each auxiliary field
1200: . a - each auxiliary field evaluated at the current point
1201: . a_t - the time derivative of each auxiliary field evaluated at the current point
1202: . a_x - the gradient of auxiliary each field evaluated at the current point
1203: . t - current time
1204: . x - coordinates of the current point
1205: . numConstants - number of constant parameters
1206: . constants - constant parameters
1207: - f0 - output values at the current point

1209:   Level: intermediate

1211:   Note:
1212:   We are using a first order FEM model for the weak form:  \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)

1214: .seealso: `PetscDS`, `PetscDSSetResidual()`
1215: @*/
1216: 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[]))
1217: {
1218:   PetscPointFunc *tmp0, *tmp1;
1219:   PetscInt        n0, n1;

1221:   PetscFunctionBegin;
1223:   PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
1224:   PetscCall(PetscWeakFormGetResidual(ds->wf, NULL, 0, f, 0, &n0, &tmp0, &n1, &tmp1));
1225:   *f0 = tmp0 ? tmp0[0] : NULL;
1226:   *f1 = tmp1 ? tmp1[0] : NULL;
1227:   PetscFunctionReturn(PETSC_SUCCESS);
1228: }

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

1233:   Not collective

1235:   Input Parameters:
1236: + ds - The `PetscDS`
1237: . f  - The test field number
1238: . f0 - integrand for the test function term
1239: - f1 - integrand for the test function gradient term

1241:   Calling sequence for the callbacks f0 and f1:
1242: .vb
1243:   f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1244:      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1245:      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1246:      PetscReal t, const PetscReal x[], PetscScalar f0[])
1247: .ve
1248: + dim - the spatial dimension
1249: . Nf - the number of fields
1250: . uOff - the offset into u[] and u_t[] for each field
1251: . uOff_x - the offset into u_x[] for each field
1252: . u - each field evaluated at the current point
1253: . u_t - the time derivative of each field evaluated at the current point
1254: . u_x - the gradient of each field evaluated at the current point
1255: . aOff - the offset into a[] and a_t[] for each auxiliary field
1256: . aOff_x - the offset into a_x[] for each auxiliary field
1257: . a - each auxiliary field evaluated at the current point
1258: . a_t - the time derivative of each auxiliary field evaluated at the current point
1259: . a_x - the gradient of auxiliary each field evaluated at the current point
1260: . t - current time
1261: . x - coordinates of the current point
1262: . numConstants - number of constant parameters
1263: . constants - constant parameters
1264: - f0 - output values at the current point

1266:   Level: intermediate

1268:   Note:
1269:   We are using a first order FEM model for the weak form:  \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)

1271: .seealso: `PetscDS`, `PetscDSGetResidual()`
1272: @*/
1273: 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[]))
1274: {
1275:   PetscFunctionBegin;
1279:   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1280:   PetscCall(PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1));
1281:   PetscFunctionReturn(PETSC_SUCCESS);
1282: }

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

1287:   Not collective

1289:   Input Parameters:
1290: + ds - The `PetscDS`
1291: - f  - The test field number

1293:   Output Parameters:
1294: + f0 - integrand for the test function term
1295: - f1 - integrand for the test function gradient term

1297:   Calling sequence for the callbacks f0 and f1:
1298: .vb
1299:   f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1300:      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1301:      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1302:     PetscReal t, const PetscReal x[], PetscScalar f0[])
1303: .ve
1304: + dim - the spatial dimension
1305: . Nf - the number of fields
1306: . uOff - the offset into u[] and u_t[] for each field
1307: . uOff_x - the offset into u_x[] for each field
1308: . u - each field evaluated at the current point
1309: . u_t - the time derivative of each field evaluated at the current point
1310: . u_x - the gradient of each field evaluated at the current point
1311: . aOff - the offset into a[] and a_t[] for each auxiliary field
1312: . aOff_x - the offset into a_x[] for each auxiliary field
1313: . a - each auxiliary field evaluated at the current point
1314: . a_t - the time derivative of each auxiliary field evaluated at the current point
1315: . a_x - the gradient of auxiliary each field evaluated at the current point
1316: . t - current time
1317: . x - coordinates of the current point
1318: . numConstants - number of constant parameters
1319: . constants - constant parameters
1320: - f0 - output values at the current point

1322:   Level: intermediate

1324:   Note:
1325:   We are using a first order FEM model for the weak form: \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)

1327: .seealso: `PetscDS`, `PetscDSSetRHSResidual()`
1328: @*/
1329: 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[]))
1330: {
1331:   PetscPointFunc *tmp0, *tmp1;
1332:   PetscInt        n0, n1;

1334:   PetscFunctionBegin;
1336:   PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
1337:   PetscCall(PetscWeakFormGetResidual(ds->wf, NULL, 0, f, 100, &n0, &tmp0, &n1, &tmp1));
1338:   *f0 = tmp0 ? tmp0[0] : NULL;
1339:   *f1 = tmp1 ? tmp1[0] : NULL;
1340:   PetscFunctionReturn(PETSC_SUCCESS);
1341: }

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

1346:   Not collective

1348:   Input Parameters:
1349: + ds - The `PetscDS`
1350: . f  - The test field number
1351: . f0 - integrand for the test function term
1352: - f1 - integrand for the test function gradient term

1354:   Clling sequence for the callbacks f0 and f1:
1355: .vb
1356:   f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1357:      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1358:      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1359:      PetscReal t, const PetscReal x[], PetscScalar f0[])
1360: .ve
1361: + dim - the spatial dimension
1362: . Nf - the number of fields
1363: . uOff - the offset into u[] and u_t[] for each field
1364: . uOff_x - the offset into u_x[] for each field
1365: . u - each field evaluated at the current point
1366: . u_t - the time derivative of each field evaluated at the current point
1367: . u_x - the gradient of each field evaluated at the current point
1368: . aOff - the offset into a[] and a_t[] for each auxiliary field
1369: . aOff_x - the offset into a_x[] for each auxiliary field
1370: . a - each auxiliary field evaluated at the current point
1371: . a_t - the time derivative of each auxiliary field evaluated at the current point
1372: . a_x - the gradient of auxiliary each field evaluated at the current point
1373: . t - current time
1374: . x - coordinates of the current point
1375: . numConstants - number of constant parameters
1376: . constants - constant parameters
1377: - f0 - output values at the current point

1379:   Level: intermediate

1381:   Note:
1382:   We are using a first order FEM model for the weak form:  \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)

1384: .seealso: `PetscDS`, `PetscDSGetResidual()`
1385: @*/
1386: 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[]))
1387: {
1388:   PetscFunctionBegin;
1392:   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1393:   PetscCall(PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 100, 0, f0, 0, f1));
1394:   PetscFunctionReturn(PETSC_SUCCESS);
1395: }

1397: /*@C
1398:   PetscDSHasJacobian - Checks that the Jacobian functions have been set

1400:   Not collective

1402:   Input Parameter:
1403: . prob - The `PetscDS`

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

1408:   Level: intermediate

1410: .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`
1411: @*/
1412: PetscErrorCode PetscDSHasJacobian(PetscDS ds, PetscBool *hasJac)
1413: {
1414:   PetscFunctionBegin;
1416:   PetscCall(PetscWeakFormHasJacobian(ds->wf, hasJac));
1417:   PetscFunctionReturn(PETSC_SUCCESS);
1418: }

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

1423:   Not collective

1425:   Input Parameters:
1426: + ds - The `PetscDS`
1427: . f  - The test field number
1428: - g  - The field number

1430:   Output Parameters:
1431: + g0 - integrand for the test and basis function term
1432: . g1 - integrand for the test function and basis function gradient term
1433: . g2 - integrand for the test function gradient and basis function term
1434: - g3 - integrand for the test function gradient and basis function gradient term

1436:   Calling sequence for the callbacks g0, g1, g2 and g3:
1437: .vb
1438:   g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1439:      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1440:      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1441:      PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])
1442: .ve
1443: + dim - the spatial dimension
1444: . Nf - the number of fields
1445: . uOff - the offset into u[] and u_t[] for each field
1446: . uOff_x - the offset into u_x[] for each field
1447: . u - each field evaluated at the current point
1448: . u_t - the time derivative of each field evaluated at the current point
1449: . u_x - the gradient of each field evaluated at the current point
1450: . aOff - the offset into a[] and a_t[] for each auxiliary field
1451: . aOff_x - the offset into a_x[] for each auxiliary field
1452: . a - each auxiliary field evaluated at the current point
1453: . a_t - the time derivative of each auxiliary field evaluated at the current point
1454: . a_x - the gradient of auxiliary each field evaluated at the current point
1455: . t - current time
1456: . u_tShift - the multiplier a for dF/dU_t
1457: . x - coordinates of the current point
1458: . numConstants - number of constant parameters
1459: . constants - constant parameters
1460: - g0 - output values at the current point

1462:   Level: intermediate

1464:   Note:
1465:   We are using a first order FEM model for the weak form:
1466:   \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

1468: .seealso: `PetscDS`, `PetscDSSetJacobian()`
1469: @*/
1470: 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[]))
1471: {
1472:   PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
1473:   PetscInt       n0, n1, n2, n3;

1475:   PetscFunctionBegin;
1477:   PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
1478:   PetscCheck(!(g < 0) && !(g >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", g, ds->Nf);
1479:   PetscCall(PetscWeakFormGetJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
1480:   *g0 = tmp0 ? tmp0[0] : NULL;
1481:   *g1 = tmp1 ? tmp1[0] : NULL;
1482:   *g2 = tmp2 ? tmp2[0] : NULL;
1483:   *g3 = tmp3 ? tmp3[0] : NULL;
1484:   PetscFunctionReturn(PETSC_SUCCESS);
1485: }

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

1490:   Not collective

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

1501:   Calling sequence for the callbacks g0, g1, g2 and g3:
1502: .vb
1503:   g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1504:      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1505:      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1506:      PetscReal t, const PetscReal x[], PetscScalar g0[])
1507: .ve
1508: + dim - the spatial dimension
1509: . Nf - the number of fields
1510: . uOff - the offset into u[] and u_t[] for each field
1511: . uOff_x - the offset into u_x[] for each field
1512: . u - each field evaluated at the current point
1513: . u_t - the time derivative of each field evaluated at the current point
1514: . u_x - the gradient of each field evaluated at the current point
1515: . aOff - the offset into a[] and a_t[] for each auxiliary field
1516: . aOff_x - the offset into a_x[] for each auxiliary field
1517: . a - each auxiliary field evaluated at the current point
1518: . a_t - the time derivative of each auxiliary field evaluated at the current point
1519: . a_x - the gradient of auxiliary each field evaluated at the current point
1520: . t - current time
1521: . u_tShift - the multiplier a for dF/dU_t
1522: . x - coordinates of the current point
1523: . numConstants - number of constant parameters
1524: . constants - constant parameters
1525: - g0 - output values at the current point

1527:   Level: intermediate

1529:   Note:
1530:    We are using a first order FEM model for the weak form:
1531:   \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

1533: .seealso: `PetscDS`, `PetscDSGetJacobian()`
1534: @*/
1535: 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[]))
1536: {
1537:   PetscFunctionBegin;
1543:   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1544:   PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
1545:   PetscCall(PetscWeakFormSetIndexJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
1546:   PetscFunctionReturn(PETSC_SUCCESS);
1547: }

1549: /*@C
1550:   PetscDSUseJacobianPreconditioner - Set whether to construct a Jacobian preconditioner

1552:   Not collective

1554:   Input Parameters:
1555: + prob - The `PetscDS`
1556: - useJacPre - flag that enables construction of a Jacobian preconditioner

1558:   Level: intermediate

1560: .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`
1561: @*/
1562: PetscErrorCode PetscDSUseJacobianPreconditioner(PetscDS prob, PetscBool useJacPre)
1563: {
1564:   PetscFunctionBegin;
1566:   prob->useJacPre = useJacPre;
1567:   PetscFunctionReturn(PETSC_SUCCESS);
1568: }

1570: /*@C
1571:   PetscDSHasJacobianPreconditioner - Checks if a Jacobian preconditioner matrix has been set

1573:   Not collective

1575:   Input Parameter:
1576: . prob - The `PetscDS`

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

1581:   Level: intermediate

1583: .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`
1584: @*/
1585: PetscErrorCode PetscDSHasJacobianPreconditioner(PetscDS ds, PetscBool *hasJacPre)
1586: {
1587:   PetscFunctionBegin;
1589:   *hasJacPre = PETSC_FALSE;
1590:   if (!ds->useJacPre) PetscFunctionReturn(PETSC_SUCCESS);
1591:   PetscCall(PetscWeakFormHasJacobianPreconditioner(ds->wf, hasJacPre));
1592:   PetscFunctionReturn(PETSC_SUCCESS);
1593: }

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

1599:   Not collective

1601:   Input Parameters:
1602: + ds - The `PetscDS`
1603: . f  - The test field number
1604: - g  - The field number

1606:   Output Parameters:
1607: + g0 - integrand for the test and basis function term
1608: . g1 - integrand for the test function and basis function gradient term
1609: . g2 - integrand for the test function gradient and basis function term
1610: - g3 - integrand for the test function gradient and basis function gradient term

1612:   Calling sequence for the callbacks g0, g1, g2 and g3:
1613: .vb
1614:   g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1615:      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1616:      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1617:      PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])
1618: .ve
1619: + dim - the spatial dimension
1620: . Nf - the number of fields
1621: . uOff - the offset into u[] and u_t[] for each field
1622: . uOff_x - the offset into u_x[] for each field
1623: . u - each field evaluated at the current point
1624: . u_t - the time derivative of each field evaluated at the current point
1625: . u_x - the gradient of each field evaluated at the current point
1626: . aOff - the offset into a[] and a_t[] for each auxiliary field
1627: . aOff_x - the offset into a_x[] for each auxiliary field
1628: . a - each auxiliary field evaluated at the current point
1629: . a_t - the time derivative of each auxiliary field evaluated at the current point
1630: . a_x - the gradient of auxiliary each field evaluated at the current point
1631: . t - current time
1632: . u_tShift - the multiplier a for dF/dU_t
1633: . x - coordinates of the current point
1634: . numConstants - number of constant parameters
1635: . constants - constant parameters
1636: - g0 - output values at the current point

1638:   Level: intermediate

1640:   Note:
1641:   We are using a first order FEM model for the weak form:
1642:   \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

1644: .seealso: `PetscDS`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`
1645: @*/
1646: 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[]))
1647: {
1648:   PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
1649:   PetscInt       n0, n1, n2, n3;

1651:   PetscFunctionBegin;
1653:   PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
1654:   PetscCheck(!(g < 0) && !(g >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", g, ds->Nf);
1655:   PetscCall(PetscWeakFormGetJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
1656:   *g0 = tmp0 ? tmp0[0] : NULL;
1657:   *g1 = tmp1 ? tmp1[0] : NULL;
1658:   *g2 = tmp2 ? tmp2[0] : NULL;
1659:   *g3 = tmp3 ? tmp3[0] : NULL;
1660:   PetscFunctionReturn(PETSC_SUCCESS);
1661: }

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

1667:   Not collective

1669:   Input Parameters:
1670: + ds - The `PetscDS`
1671: . f  - The test field number
1672: . g  - The field number
1673: . g0 - integrand for the test and basis function term
1674: . g1 - integrand for the test function and basis function gradient term
1675: . g2 - integrand for the test function gradient and basis function term
1676: - g3 - integrand for the test function gradient and basis function gradient term

1678:   Calling sequence for the callbacks g0, g1, g2 and g3:
1679: .vb
1680:   g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1681:      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1682:      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1683:      PetscReal t, const PetscReal x[], PetscScalar g0[])
1684: .ve
1685: + dim - the spatial dimension
1686: . Nf - the number of fields
1687: . uOff - the offset into u[] and u_t[] for each field
1688: . uOff_x - the offset into u_x[] for each field
1689: . u - each field evaluated at the current point
1690: . u_t - the time derivative of each field evaluated at the current point
1691: . u_x - the gradient of each field evaluated at the current point
1692: . aOff - the offset into a[] and a_t[] for each auxiliary field
1693: . aOff_x - the offset into a_x[] for each auxiliary field
1694: . a - each auxiliary field evaluated at the current point
1695: . a_t - the time derivative of each auxiliary field evaluated at the current point
1696: . a_x - the gradient of auxiliary each field evaluated at the current point
1697: . t - current time
1698: . u_tShift - the multiplier a for dF/dU_t
1699: . x - coordinates of the current point
1700: . numConstants - number of constant parameters
1701: . constants - constant parameters
1702: - g0 - output values at the current point

1704:   Level: intermediate

1706:   Note:
1707:   We are using a first order FEM model for the weak form:
1708:   \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

1710: .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobian()`
1711: @*/
1712: 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[]))
1713: {
1714:   PetscFunctionBegin;
1720:   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1721:   PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
1722:   PetscCall(PetscWeakFormSetIndexJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
1723:   PetscFunctionReturn(PETSC_SUCCESS);
1724: }

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

1729:   Not collective

1731:   Input Parameter:
1732: . ds - The `PetscDS`

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

1737:   Level: intermediate

1739: .seealso: `PetscDS`, `PetscDSGetDynamicJacobian()`, `PetscDSSetDynamicJacobian()`, `PetscDSGetJacobian()`
1740: @*/
1741: PetscErrorCode PetscDSHasDynamicJacobian(PetscDS ds, PetscBool *hasDynJac)
1742: {
1743:   PetscFunctionBegin;
1745:   PetscCall(PetscWeakFormHasDynamicJacobian(ds->wf, hasDynJac));
1746:   PetscFunctionReturn(PETSC_SUCCESS);
1747: }

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

1752:   Not collective

1754:   Input Parameters:
1755: + ds - The `PetscDS`
1756: . f  - The test field number
1757: - g  - The field number

1759:   Output Parameters:
1760: + g0 - integrand for the test and basis function term
1761: . g1 - integrand for the test function and basis function gradient term
1762: . g2 - integrand for the test function gradient and basis function term
1763: - g3 - integrand for the test function gradient and basis function gradient term

1765:    Calling sequence for the callbacks g0, g1, g2 and g3:
1766: .vb
1767:   g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1768:      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1769:      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1770:      PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])
1771: .ve
1772: + dim - the spatial dimension
1773: . Nf - the number of fields
1774: . uOff - the offset into u[] and u_t[] for each field
1775: . uOff_x - the offset into u_x[] for each field
1776: . u - each field evaluated at the current point
1777: . u_t - the time derivative of each field evaluated at the current point
1778: . u_x - the gradient of each field evaluated at the current point
1779: . aOff - the offset into a[] and a_t[] for each auxiliary field
1780: . aOff_x - the offset into a_x[] for each auxiliary field
1781: . a - each auxiliary field evaluated at the current point
1782: . a_t - the time derivative of each auxiliary field evaluated at the current point
1783: . a_x - the gradient of auxiliary each field evaluated at the current point
1784: . t - current time
1785: . u_tShift - the multiplier a for dF/dU_t
1786: . x - coordinates of the current point
1787: . numConstants - number of constant parameters
1788: . constants - constant parameters
1789: - g0 - output values at the current point

1791:   Level: intermediate

1793:   Note:
1794:   We are using a first order FEM model for the weak form:
1795:   \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

1797: .seealso: `PetscDS`, `PetscDSSetJacobian()`
1798: @*/
1799: 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[]))
1800: {
1801:   PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
1802:   PetscInt       n0, n1, n2, n3;

1804:   PetscFunctionBegin;
1806:   PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
1807:   PetscCheck(!(g < 0) && !(g >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", g, ds->Nf);
1808:   PetscCall(PetscWeakFormGetDynamicJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
1809:   *g0 = tmp0 ? tmp0[0] : NULL;
1810:   *g1 = tmp1 ? tmp1[0] : NULL;
1811:   *g2 = tmp2 ? tmp2[0] : NULL;
1812:   *g3 = tmp3 ? tmp3[0] : NULL;
1813:   PetscFunctionReturn(PETSC_SUCCESS);
1814: }

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

1819:   Not collective

1821:   Input Parameters:
1822: + ds - The `PetscDS`
1823: . f  - The test field number
1824: . g  - The field number
1825: . g0 - integrand for the test and basis function term
1826: . g1 - integrand for the test function and basis function gradient term
1827: . g2 - integrand for the test function gradient and basis function term
1828: - g3 - integrand for the test function gradient and basis function gradient term

1830:   Calling sequence for the callbacks g0, g1, g2 and g3:
1831: .vb
1832:    g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1833:      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1834:      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1835:      PetscReal t, const PetscReal x[], PetscScalar g0[])
1836: .ve
1837: + dim - the spatial dimension
1838: . Nf - the number of fields
1839: . uOff - the offset into u[] and u_t[] for each field
1840: . uOff_x - the offset into u_x[] for each field
1841: . u - each field evaluated at the current point
1842: . u_t - the time derivative of each field evaluated at the current point
1843: . u_x - the gradient of each field evaluated at the current point
1844: . aOff - the offset into a[] and a_t[] for each auxiliary field
1845: . aOff_x - the offset into a_x[] for each auxiliary field
1846: . a - each auxiliary field evaluated at the current point
1847: . a_t - the time derivative of each auxiliary field evaluated at the current point
1848: . a_x - the gradient of auxiliary each field evaluated at the current point
1849: . t - current time
1850: . u_tShift - the multiplier a for dF/dU_t
1851: . x - coordinates of the current point
1852: . numConstants - number of constant parameters
1853: . constants - constant parameters
1854: - g0 - output values at the current point

1856:   Level: intermediate

1858:   Note:
1859:   We are using a first order FEM model for the weak form:
1860:   \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

1862: .seealso: `PetscDS`, `PetscDSGetJacobian()`
1863: @*/
1864: 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[]))
1865: {
1866:   PetscFunctionBegin;
1872:   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1873:   PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
1874:   PetscCall(PetscWeakFormSetIndexDynamicJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
1875:   PetscFunctionReturn(PETSC_SUCCESS);
1876: }

1878: /*@C
1879:   PetscDSGetRiemannSolver - Returns the Riemann solver for the given field

1881:   Not collective

1883:   Input Parameters:
1884: + ds - The `PetscDS` object
1885: - f  - The field number

1887:   Output Parameter:
1888: . r    - Riemann solver

1890:   Calling sequence for r:
1891: .vb
1892:   r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx)
1893: .ve
1894: + dim  - The spatial dimension
1895: . Nf   - The number of fields
1896: . x    - The coordinates at a point on the interface
1897: . n    - The normal vector to the interface
1898: . uL   - The state vector to the left of the interface
1899: . uR   - The state vector to the right of the interface
1900: . flux - output array of flux through the interface
1901: . numConstants - number of constant parameters
1902: . constants - constant parameters
1903: - ctx  - optional user context

1905:   Level: intermediate

1907: .seealso: `PetscDS`, `PetscDSSetRiemannSolver()`
1908: @*/
1909: 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))
1910: {
1911:   PetscRiemannFunc *tmp;
1912:   PetscInt          n;

1914:   PetscFunctionBegin;
1917:   PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
1918:   PetscCall(PetscWeakFormGetRiemannSolver(ds->wf, NULL, 0, f, 0, &n, &tmp));
1919:   *r = tmp ? tmp[0] : NULL;
1920:   PetscFunctionReturn(PETSC_SUCCESS);
1921: }

1923: /*@C
1924:   PetscDSSetRiemannSolver - Sets the Riemann solver for the given field

1926:   Not collective

1928:   Input Parameters:
1929: + ds - The `PetscDS` object
1930: . f  - The field number
1931: - r  - Riemann solver

1933:   Calling sequence for r:
1934: .vb
1935:    r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx)
1936: .ve
1937: + dim  - The spatial dimension
1938: . Nf   - The number of fields
1939: . x    - The coordinates at a point on the interface
1940: . n    - The normal vector to the interface
1941: . uL   - The state vector to the left of the interface
1942: . uR   - The state vector to the right of the interface
1943: . flux - output array of flux through the interface
1944: . numConstants - number of constant parameters
1945: . constants - constant parameters
1946: - ctx  - optional user context

1948:   Level: intermediate

1950: .seealso: `PetscDS`, `PetscDSGetRiemannSolver()`
1951: @*/
1952: 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))
1953: {
1954:   PetscFunctionBegin;
1957:   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1958:   PetscCall(PetscWeakFormSetIndexRiemannSolver(ds->wf, NULL, 0, f, 0, 0, r));
1959:   PetscFunctionReturn(PETSC_SUCCESS);
1960: }

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

1965:   Not collective

1967:   Input Parameters:
1968: + ds - The `PetscDS`
1969: - f  - The field number

1971:   Output Parameter:
1972: . update - update function

1974:   Calling sequence for the callback update:
1975: .vb
1976:   update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1977:          const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1978:          const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1979:          PetscReal t, const PetscReal x[], PetscScalar uNew[])
1980: .ve
1981: + dim - the spatial dimension
1982: . Nf - the number of fields
1983: . uOff - the offset into u[] and u_t[] for each field
1984: . uOff_x - the offset into u_x[] for each field
1985: . u - each field evaluated at the current point
1986: . u_t - the time derivative of each field evaluated at the current point
1987: . u_x - the gradient of each field evaluated at the current point
1988: . aOff - the offset into a[] and a_t[] for each auxiliary field
1989: . aOff_x - the offset into a_x[] for each auxiliary field
1990: . a - each auxiliary field evaluated at the current point
1991: . a_t - the time derivative of each auxiliary field evaluated at the current point
1992: . a_x - the gradient of auxiliary each field evaluated at the current point
1993: . t - current time
1994: . x - coordinates of the current point
1995: - uNew - new value for field at the current point

1997:   Level: intermediate

1999: .seealso: `PetscDS`, `PetscDSSetUpdate()`, `PetscDSSetResidual()`
2000: @*/
2001: 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[]))
2002: {
2003:   PetscFunctionBegin;
2005:   PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
2006:   if (update) {
2008:     *update = ds->update[f];
2009:   }
2010:   PetscFunctionReturn(PETSC_SUCCESS);
2011: }

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

2016:   Not collective

2018:   Input Parameters:
2019: + ds     - The `PetscDS`
2020: . f      - The field number
2021: - update - update function

2023:   Calling sequence for the callback update:
2024: .vb
2025:   update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2026:          const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2027:          const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2028:          PetscReal t, const PetscReal x[], PetscScalar uNew[])
2029: .ve
2030: + dim - the spatial dimension
2031: . Nf - the number of fields
2032: . uOff - the offset into u[] and u_t[] for each field
2033: . uOff_x - the offset into u_x[] for each field
2034: . u - each field evaluated at the current point
2035: . u_t - the time derivative of each field evaluated at the current point
2036: . u_x - the gradient of each field evaluated at the current point
2037: . aOff - the offset into a[] and a_t[] for each auxiliary field
2038: . aOff_x - the offset into a_x[] for each auxiliary field
2039: . a - each auxiliary field evaluated at the current point
2040: . a_t - the time derivative of each auxiliary field evaluated at the current point
2041: . a_x - the gradient of auxiliary each field evaluated at the current point
2042: . t - current time
2043: . x - coordinates of the current point
2044: - uNew - new field values at the current point

2046:   Level: intermediate

2048: .seealso: `PetscDS`, `PetscDSGetResidual()`
2049: @*/
2050: 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[]))
2051: {
2052:   PetscFunctionBegin;
2055:   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2056:   PetscCall(PetscDSEnlarge_Static(ds, f + 1));
2057:   ds->update[f] = update;
2058:   PetscFunctionReturn(PETSC_SUCCESS);
2059: }

2061: PetscErrorCode PetscDSGetContext(PetscDS ds, PetscInt f, void *ctx)
2062: {
2063:   PetscFunctionBegin;
2065:   PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
2067:   *(void **)ctx = ds->ctx[f];
2068:   PetscFunctionReturn(PETSC_SUCCESS);
2069: }

2071: PetscErrorCode PetscDSSetContext(PetscDS ds, PetscInt f, void *ctx)
2072: {
2073:   PetscFunctionBegin;
2075:   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2076:   PetscCall(PetscDSEnlarge_Static(ds, f + 1));
2077:   ds->ctx[f] = ctx;
2078:   PetscFunctionReturn(PETSC_SUCCESS);
2079: }

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

2084:   Not collective

2086:   Input Parameters:
2087: + ds - The PetscDS
2088: - f  - The test field number

2090:   Output Parameters:
2091: + f0 - boundary integrand for the test function term
2092: - f1 - boundary integrand for the test function gradient term

2094:   Calling sequence for the callbacks f0 and f1:
2095: .vb
2096:   f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2097:      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2098:      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2099:      PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])
2100: .ve
2101: + dim - the spatial dimension
2102: . Nf - the number of fields
2103: . uOff - the offset into u[] and u_t[] for each field
2104: . uOff_x - the offset into u_x[] for each field
2105: . u - each field evaluated at the current point
2106: . u_t - the time derivative of each field evaluated at the current point
2107: . u_x - the gradient of each field evaluated at the current point
2108: . aOff - the offset into a[] and a_t[] for each auxiliary field
2109: . aOff_x - the offset into a_x[] for each auxiliary field
2110: . a - each auxiliary field evaluated at the current point
2111: . a_t - the time derivative of each auxiliary field evaluated at the current point
2112: . a_x - the gradient of auxiliary each field evaluated at the current point
2113: . t - current time
2114: . x - coordinates of the current point
2115: . n - unit normal at the current point
2116: . numConstants - number of constant parameters
2117: . constants - constant parameters
2118: - f0 - output values at the current point

2120:   Level: intermediate

2122:   Note:
2123:   We are using a first order FEM model for the weak form:
2124:   \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

2126: .seealso: `PetscDS`, `PetscDSSetBdResidual()`
2127: @*/
2128: 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[]))
2129: {
2130:   PetscBdPointFunc *tmp0, *tmp1;
2131:   PetscInt          n0, n1;

2133:   PetscFunctionBegin;
2135:   PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
2136:   PetscCall(PetscWeakFormGetBdResidual(ds->wf, NULL, 0, f, 0, &n0, &tmp0, &n1, &tmp1));
2137:   *f0 = tmp0 ? tmp0[0] : NULL;
2138:   *f1 = tmp1 ? tmp1[0] : NULL;
2139:   PetscFunctionReturn(PETSC_SUCCESS);
2140: }

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

2145:   Not collective

2147:   Input Parameters:
2148: + ds - The `PetscDS`
2149: . f  - The test field number
2150: . f0 - boundary integrand for the test function term
2151: - f1 - boundary integrand for the test function gradient term

2153:   Calling sequence for the callbacks f0 and f1:
2154: .vb
2155:   f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2156:      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2157:      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2158:      PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])
2159: .ve
2160: + dim - the spatial dimension
2161: . Nf - the number of fields
2162: . uOff - the offset into u[] and u_t[] for each field
2163: . uOff_x - the offset into u_x[] for each field
2164: . u - each field evaluated at the current point
2165: . u_t - the time derivative of each field evaluated at the current point
2166: . u_x - the gradient of each field evaluated at the current point
2167: . aOff - the offset into a[] and a_t[] for each auxiliary field
2168: . aOff_x - the offset into a_x[] for each auxiliary field
2169: . a - each auxiliary field evaluated at the current point
2170: . a_t - the time derivative of each auxiliary field evaluated at the current point
2171: . a_x - the gradient of auxiliary each field evaluated at the current point
2172: . t - current time
2173: . x - coordinates of the current point
2174: . n - unit normal at the current point
2175: . numConstants - number of constant parameters
2176: . constants - constant parameters
2177: - f0 - output values at the current point

2179:   Level: intermediate

2181:   Note:
2182:   We are using a first order FEM model for the weak form:
2183:   \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

2185: .seealso: `PetscDS`, `PetscDSGetBdResidual()`
2186: @*/
2187: 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[]))
2188: {
2189:   PetscFunctionBegin;
2191:   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2192:   PetscCall(PetscWeakFormSetIndexBdResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1));
2193:   PetscFunctionReturn(PETSC_SUCCESS);
2194: }

2196: /*@
2197:   PetscDSHasBdJacobian - Indicates that boundary Jacobian functions have been set

2199:   Not collective

2201:   Input Parameter:
2202: . ds - The `PetscDS`

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

2207:   Level: intermediate

2209: .seealso: `PetscDS`, `PetscDSHasJacobian()`, `PetscDSSetBdJacobian()`, `PetscDSGetBdJacobian()`
2210: @*/
2211: PetscErrorCode PetscDSHasBdJacobian(PetscDS ds, PetscBool *hasBdJac)
2212: {
2213:   PetscFunctionBegin;
2216:   PetscCall(PetscWeakFormHasBdJacobian(ds->wf, hasBdJac));
2217:   PetscFunctionReturn(PETSC_SUCCESS);
2218: }

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

2223:   Not collective

2225:   Input Parameters:
2226: + ds - The `PetscDS`
2227: . f  - The test field number
2228: - g  - The field number

2230:   Output Parameters:
2231: + g0 - integrand for the test and basis function term
2232: . g1 - integrand for the test function and basis function gradient term
2233: . g2 - integrand for the test function gradient and basis function term
2234: - g3 - integrand for the test function gradient and basis function gradient term

2236:   Calling sequence for the callbacks g0, g1, g2 and g3:
2237: .vb
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[])
2242: .ve
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:   Note:
2266:   We are using a first order FEM model for the weak form:
2267:   \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

2269: .seealso: `PetscDS`, `PetscDSSetBdJacobian()`
2270: @*/
2271: 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[]))
2272: {
2273:   PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3;
2274:   PetscInt         n0, n1, n2, n3;

2276:   PetscFunctionBegin;
2278:   PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
2279:   PetscCheck(!(g < 0) && !(g >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", g, ds->Nf);
2280:   PetscCall(PetscWeakFormGetBdJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
2281:   *g0 = tmp0 ? tmp0[0] : NULL;
2282:   *g1 = tmp1 ? tmp1[0] : NULL;
2283:   *g2 = tmp2 ? tmp2[0] : NULL;
2284:   *g3 = tmp3 ? tmp3[0] : NULL;
2285:   PetscFunctionReturn(PETSC_SUCCESS);
2286: }

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

2291:   Not collective

2293:   Input Parameters:
2294: + ds - The PetscDS
2295: . f  - The test field number
2296: . g  - The field number
2297: . g0 - integrand for the test and basis function term
2298: . g1 - integrand for the test function and basis function gradient term
2299: . g2 - integrand for the test function gradient and basis function term
2300: - g3 - integrand for the test function gradient and basis function gradient term

2302:   Calling sequence for the callbacks g0, g1, g2 and g3:
2303: .vb
2304:   g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2305:      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2306:      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2307:      PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[])
2308: .ve
2309: + dim - the spatial dimension
2310: . Nf - the number of fields
2311: . uOff - the offset into u[] and u_t[] for each field
2312: . uOff_x - the offset into u_x[] for each field
2313: . u - each field evaluated at the current point
2314: . u_t - the time derivative of each field evaluated at the current point
2315: . u_x - the gradient of each field evaluated at the current point
2316: . aOff - the offset into a[] and a_t[] for each auxiliary field
2317: . aOff_x - the offset into a_x[] for each auxiliary field
2318: . a - each auxiliary field evaluated at the current point
2319: . a_t - the time derivative of each auxiliary field evaluated at the current point
2320: . a_x - the gradient of auxiliary each field evaluated at the current point
2321: . t - current time
2322: . u_tShift - the multiplier a for dF/dU_t
2323: . x - coordinates of the current point
2324: . n - normal at the current point
2325: . numConstants - number of constant parameters
2326: . constants - constant parameters
2327: - g0 - output values at the current point

2329:   Level: intermediate

2331:   Note:
2332:   We are using a first order FEM model for the weak form:
2333:   \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

2335: .seealso: `PetscDS`, `PetscDSGetBdJacobian()`
2336: @*/
2337: 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[]))
2338: {
2339:   PetscFunctionBegin;
2345:   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2346:   PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
2347:   PetscCall(PetscWeakFormSetIndexBdJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
2348:   PetscFunctionReturn(PETSC_SUCCESS);
2349: }

2351: /*@
2352:   PetscDSHasBdJacobianPreconditioner - Signals that boundary Jacobian preconditioner functions have been set

2354:   Not collective

2356:   Input Parameter:
2357: . ds - The `PetscDS`

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

2362:   Level: intermediate

2364: .seealso: `PetscDS`, `PetscDSHasJacobian()`, `PetscDSSetBdJacobian()`, `PetscDSGetBdJacobian()`
2365: @*/
2366: PetscErrorCode PetscDSHasBdJacobianPreconditioner(PetscDS ds, PetscBool *hasBdJacPre)
2367: {
2368:   PetscFunctionBegin;
2371:   PetscCall(PetscWeakFormHasBdJacobianPreconditioner(ds->wf, hasBdJacPre));
2372:   PetscFunctionReturn(PETSC_SUCCESS);
2373: }

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

2378:   Not collective

2380:   Input Parameters:
2381: + ds - The `PetscDS`
2382: . f  - The test field number
2383: - g  - The field number

2385:   Output Parameters:
2386: + g0 - integrand for the test and basis function term
2387: . g1 - integrand for the test function and basis function gradient term
2388: . g2 - integrand for the test function gradient and basis function term
2389: - g3 - integrand for the test function gradient and basis function gradient term

2391:    Calling sequence for the callbacks g0, g1, g2 and g3:
2392: .vb
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[])
2397: .ve
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:   Level: intermediate

2421:   Note:
2422:   We are using a first order FEM model for the weak form:
2423:   \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

2425:   Fortran Note:
2426:   This is not yet available in Fortran.

2428: .seealso: `PetscDS`, `PetscDSSetBdJacobianPreconditioner()`
2429: @*/
2430: 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[]))
2431: {
2432:   PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3;
2433:   PetscInt         n0, n1, n2, n3;

2435:   PetscFunctionBegin;
2437:   PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
2438:   PetscCheck(!(g < 0) && !(g >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", g, ds->Nf);
2439:   PetscCall(PetscWeakFormGetBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
2440:   *g0 = tmp0 ? tmp0[0] : NULL;
2441:   *g1 = tmp1 ? tmp1[0] : NULL;
2442:   *g2 = tmp2 ? tmp2[0] : NULL;
2443:   *g3 = tmp3 ? tmp3[0] : NULL;
2444:   PetscFunctionReturn(PETSC_SUCCESS);
2445: }

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

2450:   Not collective

2452:   Input Parameters:
2453: + ds - The `PetscDS`
2454: . f  - The test field number
2455: . g  - The field number
2456: . g0 - integrand for the test and basis function term
2457: . g1 - integrand for the test function and basis function gradient term
2458: . g2 - integrand for the test function gradient and basis function term
2459: - g3 - integrand for the test function gradient and basis function gradient term

2461:    Calling sequence for the callbacks g0, g1, g2 and g3:
2462: .vb
2463:   g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2464:      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2465:      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2466:      PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
2467: .ve
2468: + dim - the spatial dimension
2469: . Nf - the number of fields
2470: . NfAux - the number of auxiliary fields
2471: . uOff - the offset into u[] and u_t[] for each field
2472: . uOff_x - the offset into u_x[] for each field
2473: . u - each field evaluated at the current point
2474: . u_t - the time derivative of each field evaluated at the current point
2475: . u_x - the gradient of each field evaluated at the current point
2476: . aOff - the offset into a[] and a_t[] for each auxiliary field
2477: . aOff_x - the offset into a_x[] for each auxiliary field
2478: . a - each auxiliary field evaluated at the current point
2479: . a_t - the time derivative of each auxiliary field evaluated at the current point
2480: . a_x - the gradient of auxiliary each field evaluated at the current point
2481: . t - current time
2482: . u_tShift - the multiplier a for dF/dU_t
2483: . x - coordinates of the current point
2484: . n - normal at the current point
2485: . numConstants - number of constant parameters
2486: . constants - constant parameters
2487: - g0 - output values at the current point

2489:   Level: intermediate

2491:   Note:
2492:   We are using a first order FEM model for the weak form:
2493:   \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

2495:   Fortran Note:
2496:   This is not yet available in Fortran.

2498: .seealso: `PetscDS`, `PetscDSGetBdJacobianPreconditioner()`
2499: @*/
2500: 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[]))
2501: {
2502:   PetscFunctionBegin;
2508:   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2509:   PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
2510:   PetscCall(PetscWeakFormSetIndexBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
2511:   PetscFunctionReturn(PETSC_SUCCESS);
2512: }

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

2517:   Not collective

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

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

2527:   Calling sequence for the solution functions:
2528: .vb
2529:   sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2530: .ve
2531: + dim - the spatial dimension
2532: . t - current time
2533: . x - coordinates of the current point
2534: . Nc - the number of field components
2535: . u - the solution field evaluated at the current point
2536: - ctx - a user context

2538:   Level: intermediate

2540: .seealso: `PetscDS`, `PetscDSSetExactSolution()`, `PetscDSGetExactSolutionTimeDerivative()`
2541: @*/
2542: PetscErrorCode PetscDSGetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx)
2543: {
2544:   PetscFunctionBegin;
2546:   PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf);
2547:   if (sol) {
2549:     *sol = prob->exactSol[f];
2550:   }
2551:   if (ctx) {
2553:     *ctx = prob->exactCtx[f];
2554:   }
2555:   PetscFunctionReturn(PETSC_SUCCESS);
2556: }

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

2561:   Not collective

2563:   Input Parameters:
2564: + prob - The `PetscDS`
2565: . f    - The test field number
2566: . sol  - solution function for the test fields
2567: - ctx  - solution context or NULL

2569:   Calling sequence for solution functions:
2570: .vb
2571:   sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2572: .ve
2573: + dim - the spatial dimension
2574: . t - current time
2575: . x - coordinates of the current point
2576: . Nc - the number of field components
2577: . u - the solution field evaluated at the current point
2578: - ctx - a user context

2580:   Level: intermediate

2582: .seealso: `PetscDS`, `PetscDSGetExactSolution()`
2583: @*/
2584: PetscErrorCode PetscDSSetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx)
2585: {
2586:   PetscFunctionBegin;
2588:   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2589:   PetscCall(PetscDSEnlarge_Static(prob, f + 1));
2590:   if (sol) {
2592:     prob->exactSol[f] = sol;
2593:   }
2594:   if (ctx) {
2596:     prob->exactCtx[f] = ctx;
2597:   }
2598:   PetscFunctionReturn(PETSC_SUCCESS);
2599: }

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

2604:   Not collective

2606:   Input Parameters:
2607: + prob - The `PetscDS`
2608: - f    - The test field number

2610:   Output Parameters:
2611: + exactSol - time derivative of the exact solution for the test field
2612: - exactCtx - time derivative of the exact solution context

2614:   Calling sequence for the solution functions:
2615: .vb
2616:   sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2617: .ve
2618: + dim - the spatial dimension
2619: . t - current time
2620: . x - coordinates of the current point
2621: . Nc - the number of field components
2622: . u - the solution field evaluated at the current point
2623: - ctx - a user context

2625:   Level: intermediate

2627: .seealso: `PetscDS`, `PetscDSSetExactSolutionTimeDerivative()`, `PetscDSGetExactSolution()`
2628: @*/
2629: PetscErrorCode PetscDSGetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx)
2630: {
2631:   PetscFunctionBegin;
2633:   PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf);
2634:   if (sol) {
2636:     *sol = prob->exactSol_t[f];
2637:   }
2638:   if (ctx) {
2640:     *ctx = prob->exactCtx_t[f];
2641:   }
2642:   PetscFunctionReturn(PETSC_SUCCESS);
2643: }

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

2648:   Not collective

2650:   Input Parameters:
2651: + prob - The `PetscDS`
2652: . f    - The test field number
2653: . sol  - time derivative of the solution function for the test fields
2654: - ctx  - time derivative of the solution context or NULL

2656:   Calling sequence for solution functions:
2657: .vb
2658:   sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2659: .ve
2660: + dim - the spatial dimension
2661: . t - current time
2662: . x - coordinates of the current point
2663: . Nc - the number of field components
2664: . u - the solution field evaluated at the current point
2665: - ctx - a user context

2667:   Level: intermediate

2669: .seealso: `PetscDS`, `PetscDSGetExactSolutionTimeDerivative()`, `PetscDSSetExactSolution()`
2670: @*/
2671: PetscErrorCode PetscDSSetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx)
2672: {
2673:   PetscFunctionBegin;
2675:   PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2676:   PetscCall(PetscDSEnlarge_Static(prob, f + 1));
2677:   if (sol) {
2679:     prob->exactSol_t[f] = sol;
2680:   }
2681:   if (ctx) {
2683:     prob->exactCtx_t[f] = ctx;
2684:   }
2685:   PetscFunctionReturn(PETSC_SUCCESS);
2686: }

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

2691:   Not collective

2693:   Input Parameter:
2694: . prob - The `PetscDS` object

2696:   Output Parameters:
2697: + numConstants - The number of constants
2698: - constants    - The array of constants, NULL if there are none

2700:   Level: intermediate

2702: .seealso: `PetscDS`, `PetscDSSetConstants()`, `PetscDSCreate()`
2703: @*/
2704: PetscErrorCode PetscDSGetConstants(PetscDS prob, PetscInt *numConstants, const PetscScalar *constants[])
2705: {
2706:   PetscFunctionBegin;
2708:   if (numConstants) {
2710:     *numConstants = prob->numConstants;
2711:   }
2712:   if (constants) {
2714:     *constants = prob->constants;
2715:   }
2716:   PetscFunctionReturn(PETSC_SUCCESS);
2717: }

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

2722:   Not collective

2724:   Input Parameters:
2725: + prob         - The `PetscDS` object
2726: . numConstants - The number of constants
2727: - constants    - The array of constants, NULL if there are none

2729:   Level: intermediate

2731: .seealso: `PetscDS`, `PetscDSGetConstants()`, `PetscDSCreate()`
2732: @*/
2733: PetscErrorCode PetscDSSetConstants(PetscDS prob, PetscInt numConstants, PetscScalar constants[])
2734: {
2735:   PetscFunctionBegin;
2737:   if (numConstants != prob->numConstants) {
2738:     PetscCall(PetscFree(prob->constants));
2739:     prob->numConstants = numConstants;
2740:     if (prob->numConstants) {
2741:       PetscCall(PetscMalloc1(prob->numConstants, &prob->constants));
2742:     } else {
2743:       prob->constants = NULL;
2744:     }
2745:   }
2746:   if (prob->numConstants) {
2748:     PetscCall(PetscArraycpy(prob->constants, constants, prob->numConstants));
2749:   }
2750:   PetscFunctionReturn(PETSC_SUCCESS);
2751: }

2753: /*@
2754:   PetscDSGetFieldIndex - Returns the index of the given field

2756:   Not collective

2758:   Input Parameters:
2759: + prob - The `PetscDS` object
2760: - disc - The discretization object

2762:   Output Parameter:
2763: . f - The field number

2765:   Level: beginner

2767: .seealso: `PetscDS`, `PetscGetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2768: @*/
2769: PetscErrorCode PetscDSGetFieldIndex(PetscDS prob, PetscObject disc, PetscInt *f)
2770: {
2771:   PetscInt g;

2773:   PetscFunctionBegin;
2776:   *f = -1;
2777:   for (g = 0; g < prob->Nf; ++g) {
2778:     if (disc == prob->disc[g]) break;
2779:   }
2780:   PetscCheck(g != prob->Nf, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Field not found in PetscDS.");
2781:   *f = g;
2782:   PetscFunctionReturn(PETSC_SUCCESS);
2783: }

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

2788:   Not collective

2790:   Input Parameters:
2791: + prob - The `PetscDS` object
2792: - f - The field number

2794:   Output Parameter:
2795: . size - The size

2797:   Level: beginner

2799: .seealso: `PetscDS`, `PetscDSGetFieldOffset()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2800: @*/
2801: PetscErrorCode PetscDSGetFieldSize(PetscDS prob, PetscInt f, PetscInt *size)
2802: {
2803:   PetscFunctionBegin;
2806:   PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf);
2807:   PetscCall(PetscDSSetUp(prob));
2808:   *size = prob->Nb[f];
2809:   PetscFunctionReturn(PETSC_SUCCESS);
2810: }

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

2815:   Not collective

2817:   Input Parameters:
2818: + prob - The `PetscDS` object
2819: - f - The field number

2821:   Output Parameter:
2822: . off - The offset

2824:   Level: beginner

2826: .seealso: `PetscDS`, `PetscDSGetFieldSize()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2827: @*/
2828: PetscErrorCode PetscDSGetFieldOffset(PetscDS prob, PetscInt f, PetscInt *off)
2829: {
2830:   PetscInt size, g;

2832:   PetscFunctionBegin;
2835:   PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf);
2836:   *off = 0;
2837:   for (g = 0; g < f; ++g) {
2838:     PetscCall(PetscDSGetFieldSize(prob, g, &size));
2839:     *off += size;
2840:   }
2841:   PetscFunctionReturn(PETSC_SUCCESS);
2842: }

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

2847:   Not collective

2849:   Input Parameters:
2850: + prob - The `PetscDS` object
2851: - f - The field number

2853:   Output Parameter:
2854: . off - The offset

2856:   Level: beginner

2858: .seealso: `PetscDS`, `PetscDSGetFieldSize()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2859: @*/
2860: PetscErrorCode PetscDSGetFieldOffsetCohesive(PetscDS ds, PetscInt f, PetscInt *off)
2861: {
2862:   PetscInt size, g;

2864:   PetscFunctionBegin;
2867:   PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
2868:   *off = 0;
2869:   for (g = 0; g < f; ++g) {
2870:     PetscBool cohesive;

2872:     PetscCall(PetscDSGetCohesive(ds, g, &cohesive));
2873:     PetscCall(PetscDSGetFieldSize(ds, g, &size));
2874:     *off += cohesive ? size : size * 2;
2875:   }
2876:   PetscFunctionReturn(PETSC_SUCCESS);
2877: }

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

2882:   Not collective

2884:   Input Parameter:
2885: . prob - The `PetscDS` object

2887:   Output Parameter:
2888: . dimensions - The number of dimensions

2890:   Level: beginner

2892: .seealso: `PetscDS`, `PetscDSGetComponentOffsets()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2893: @*/
2894: PetscErrorCode PetscDSGetDimensions(PetscDS prob, PetscInt *dimensions[])
2895: {
2896:   PetscFunctionBegin;
2898:   PetscCall(PetscDSSetUp(prob));
2900:   *dimensions = prob->Nb;
2901:   PetscFunctionReturn(PETSC_SUCCESS);
2902: }

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

2907:   Not collective

2909:   Input Parameter:
2910: . prob - The `PetscDS` object

2912:   Output Parameter:
2913: . components - The number of components

2915:   Level: beginner

2917: .seealso: `PetscDS`, `PetscDSGetComponentOffsets()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2918: @*/
2919: PetscErrorCode PetscDSGetComponents(PetscDS prob, PetscInt *components[])
2920: {
2921:   PetscFunctionBegin;
2923:   PetscCall(PetscDSSetUp(prob));
2925:   *components = prob->Nc;
2926:   PetscFunctionReturn(PETSC_SUCCESS);
2927: }

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

2932:   Not collective

2934:   Input Parameters:
2935: + prob - The `PetscDS` object
2936: - f - The field number

2938:   Output Parameter:
2939: . off - The offset

2941:   Level: beginner

2943: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2944: @*/
2945: PetscErrorCode PetscDSGetComponentOffset(PetscDS prob, PetscInt f, PetscInt *off)
2946: {
2947:   PetscFunctionBegin;
2950:   PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf);
2951:   PetscCall(PetscDSSetUp(prob));
2952:   *off = prob->off[f];
2953:   PetscFunctionReturn(PETSC_SUCCESS);
2954: }

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

2959:   Not collective

2961:   Input Parameter:
2962: . prob - The `PetscDS` object

2964:   Output Parameter:
2965: . offsets - The offsets

2967:   Level: beginner

2969: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2970: @*/
2971: PetscErrorCode PetscDSGetComponentOffsets(PetscDS prob, PetscInt *offsets[])
2972: {
2973:   PetscFunctionBegin;
2976:   PetscCall(PetscDSSetUp(prob));
2977:   *offsets = prob->off;
2978:   PetscFunctionReturn(PETSC_SUCCESS);
2979: }

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

2984:   Not collective

2986:   Input Parameter:
2987: . prob - The `PetscDS` object

2989:   Output Parameter:
2990: . offsets - The offsets

2992:   Level: beginner

2994: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2995: @*/
2996: PetscErrorCode PetscDSGetComponentDerivativeOffsets(PetscDS prob, PetscInt *offsets[])
2997: {
2998:   PetscFunctionBegin;
3001:   PetscCall(PetscDSSetUp(prob));
3002:   *offsets = prob->offDer;
3003:   PetscFunctionReturn(PETSC_SUCCESS);
3004: }

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

3009:   Not collective

3011:   Input Parameters:
3012: + ds - The `PetscDS` object
3013: - s  - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive

3015:   Output Parameter:
3016: . offsets - The offsets

3018:   Level: beginner

3020: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
3021: @*/
3022: PetscErrorCode PetscDSGetComponentOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[])
3023: {
3024:   PetscFunctionBegin;
3027:   PetscCheck(ds->isCohesive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cohesive offsets are only valid for a cohesive DS");
3028:   PetscCheck(!(s < 0) && !(s > 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cohesive side %" PetscInt_FMT " is not in [0, 2]", s);
3029:   PetscCall(PetscDSSetUp(ds));
3030:   *offsets = ds->offCohesive[s];
3031:   PetscFunctionReturn(PETSC_SUCCESS);
3032: }

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

3037:   Not collective

3039:   Input Parameters:
3040: + ds - The `PetscDS` object
3041: - s  - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive

3043:   Output Parameter:
3044: . offsets - The offsets

3046:   Level: beginner

3048: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
3049: @*/
3050: PetscErrorCode PetscDSGetComponentDerivativeOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[])
3051: {
3052:   PetscFunctionBegin;
3055:   PetscCheck(ds->isCohesive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cohesive offsets are only valid for a cohesive DS");
3056:   PetscCheck(!(s < 0) && !(s > 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cohesive side %" PetscInt_FMT " is not in [0, 2]", s);
3057:   PetscCall(PetscDSSetUp(ds));
3058:   *offsets = ds->offDerCohesive[s];
3059:   PetscFunctionReturn(PETSC_SUCCESS);
3060: }

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

3065:   Not collective

3067:   Input Parameter:
3068: . prob - The `PetscDS` object

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

3073:   Level: intermediate

3075: .seealso: `PetscDS`, `PetscTabulation`, `PetscDSCreate()`
3076: @*/
3077: PetscErrorCode PetscDSGetTabulation(PetscDS prob, PetscTabulation *T[])
3078: {
3079:   PetscFunctionBegin;
3082:   PetscCall(PetscDSSetUp(prob));
3083:   *T = prob->T;
3084:   PetscFunctionReturn(PETSC_SUCCESS);
3085: }

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

3090:   Not collective

3092:   Input Parameter:
3093: . prob - The `PetscDS` object

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

3098:   Level: intermediate

3100: .seealso: `PetscTabulation`, `PetscDS`, `PetscDSGetTabulation()`, `PetscDSCreate()`
3101: @*/
3102: PetscErrorCode PetscDSGetFaceTabulation(PetscDS prob, PetscTabulation *Tf[])
3103: {
3104:   PetscFunctionBegin;
3107:   PetscCall(PetscDSSetUp(prob));
3108:   *Tf = prob->Tf;
3109:   PetscFunctionReturn(PETSC_SUCCESS);
3110: }

3112: PetscErrorCode PetscDSGetEvaluationArrays(PetscDS prob, PetscScalar **u, PetscScalar **u_t, PetscScalar **u_x)
3113: {
3114:   PetscFunctionBegin;
3116:   PetscCall(PetscDSSetUp(prob));
3117:   if (u) {
3119:     *u = prob->u;
3120:   }
3121:   if (u_t) {
3123:     *u_t = prob->u_t;
3124:   }
3125:   if (u_x) {
3127:     *u_x = prob->u_x;
3128:   }
3129:   PetscFunctionReturn(PETSC_SUCCESS);
3130: }

3132: PetscErrorCode PetscDSGetWeakFormArrays(PetscDS prob, PetscScalar **f0, PetscScalar **f1, PetscScalar **g0, PetscScalar **g1, PetscScalar **g2, PetscScalar **g3)
3133: {
3134:   PetscFunctionBegin;
3136:   PetscCall(PetscDSSetUp(prob));
3137:   if (f0) {
3139:     *f0 = prob->f0;
3140:   }
3141:   if (f1) {
3143:     *f1 = prob->f1;
3144:   }
3145:   if (g0) {
3147:     *g0 = prob->g0;
3148:   }
3149:   if (g1) {
3151:     *g1 = prob->g1;
3152:   }
3153:   if (g2) {
3155:     *g2 = prob->g2;
3156:   }
3157:   if (g3) {
3159:     *g3 = prob->g3;
3160:   }
3161:   PetscFunctionReturn(PETSC_SUCCESS);
3162: }

3164: PetscErrorCode PetscDSGetWorkspace(PetscDS prob, PetscReal **x, PetscScalar **basisReal, PetscScalar **basisDerReal, PetscScalar **testReal, PetscScalar **testDerReal)
3165: {
3166:   PetscFunctionBegin;
3168:   PetscCall(PetscDSSetUp(prob));
3169:   if (x) {
3171:     *x = prob->x;
3172:   }
3173:   if (basisReal) {
3175:     *basisReal = prob->basisReal;
3176:   }
3177:   if (basisDerReal) {
3179:     *basisDerReal = prob->basisDerReal;
3180:   }
3181:   if (testReal) {
3183:     *testReal = prob->testReal;
3184:   }
3185:   if (testDerReal) {
3187:     *testDerReal = prob->testDerReal;
3188:   }
3189:   PetscFunctionReturn(PETSC_SUCCESS);
3190: }

3192: /*@C
3193:   PetscDSAddBoundary - Add a boundary condition to the model. The pointwise functions are used to provide boundary values for essential boundary conditions.
3194:   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
3195:   integrals should be performed, using the kernels from `PetscDSSetBdResidual()`.

3197:   Collective on ds

3199:   Input Parameters:
3200: + ds       - The PetscDS object
3201: . type     - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
3202: . name     - The BC name
3203: . label    - The label defining constrained points
3204: . Nv       - The number of `DMLabel` values for constrained points
3205: . values   - An array of label values for constrained points
3206: . field    - The field to constrain
3207: . Nc       - The number of constrained field components (0 will constrain all fields)
3208: . comps    - An array of constrained component numbers
3209: . bcFunc   - A pointwise function giving boundary values
3210: . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL
3211: - ctx      - An optional user context for bcFunc

3213:   Output Parameters:
3214: - bd       - The boundary number

3216:   Options Database Keys:
3217: + -bc_<boundary name> <num> - Overrides the boundary ids
3218: - -bc_<boundary name>_comp <num> - Overrides the boundary components

3220:   Level: developer

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

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

3227:   If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, then the calling sequence is:
3228: .vb
3229:   bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
3230:          const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
3231:          const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
3232:          PetscReal time, const PetscReal x[], PetscScalar bcval[])
3233: .ve
3234: + dim - the spatial dimension
3235: . Nf - the number of fields
3236: . uOff - the offset into u[] and u_t[] for each field
3237: . uOff_x - the offset into u_x[] for each field
3238: . u - each field evaluated at the current point
3239: . u_t - the time derivative of each field evaluated at the current point
3240: . u_x - the gradient of each field evaluated at the current point
3241: . aOff - the offset into a[] and a_t[] for each auxiliary field
3242: . aOff_x - the offset into a_x[] for each auxiliary field
3243: . a - each auxiliary field evaluated at the current point
3244: . a_t - the time derivative of each auxiliary field evaluated at the current point
3245: . a_x - the gradient of auxiliary each field evaluated at the current point
3246: . t - current time
3247: . x - coordinates of the current point
3248: . numConstants - number of constant parameters
3249: . constants - constant parameters
3250: - bcval - output values at the current point

3252: .seealso: `PetscDS`, `PetscWeakForm`, `DMLabel`, `DMBoundaryConditionType`, `PetscDSAddBoundaryByName()`, `PetscDSGetBoundary()`, `PetscDSSetResidual()`, `PetscDSSetBdResidual()`
3253: @*/
3254: 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)
3255: {
3256:   DSBoundary  head = ds->boundary, b;
3257:   PetscInt    n    = 0;
3258:   const char *lname;

3260:   PetscFunctionBegin;
3268:   PetscCheck(field >= 0 && field < ds->Nf, PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_OUTOFRANGE, "Field %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", field, ds->Nf);
3269:   if (Nc > 0) {
3270:     PetscInt *fcomps;
3271:     PetscInt  c;

3273:     PetscCall(PetscDSGetComponents(ds, &fcomps));
3274:     PetscCheck(Nc <= fcomps[field], PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_OUTOFRANGE, "Number of constrained components %" PetscInt_FMT " > %" PetscInt_FMT " components for field %" PetscInt_FMT, Nc, fcomps[field], field);
3275:     for (c = 0; c < Nc; ++c) {
3276:       PetscCheck(comps[c] >= 0 && comps[c] < fcomps[field], PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_OUTOFRANGE, "Constrained component[%" PetscInt_FMT "] %" PetscInt_FMT " not in [0, %" PetscInt_FMT ") components for field %" PetscInt_FMT, c, comps[c], fcomps[field], field);
3277:     }
3278:   }
3279:   PetscCall(PetscNew(&b));
3280:   PetscCall(PetscStrallocpy(name, (char **)&b->name));
3281:   PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf));
3282:   PetscCall(PetscWeakFormSetNumFields(b->wf, ds->Nf));
3283:   PetscCall(PetscMalloc1(Nv, &b->values));
3284:   if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv));
3285:   PetscCall(PetscMalloc1(Nc, &b->comps));
3286:   if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc));
3287:   PetscCall(PetscObjectGetName((PetscObject)label, &lname));
3288:   PetscCall(PetscStrallocpy(lname, (char **)&b->lname));
3289:   b->type   = type;
3290:   b->label  = label;
3291:   b->Nv     = Nv;
3292:   b->field  = field;
3293:   b->Nc     = Nc;
3294:   b->func   = bcFunc;
3295:   b->func_t = bcFunc_t;
3296:   b->ctx    = ctx;
3297:   b->next   = NULL;
3298:   /* Append to linked list so that we can preserve the order */
3299:   if (!head) ds->boundary = b;
3300:   while (head) {
3301:     if (!head->next) {
3302:       head->next = b;
3303:       head       = b;
3304:     }
3305:     head = head->next;
3306:     ++n;
3307:   }
3308:   if (bd) {
3310:     *bd = n;
3311:   }
3312:   PetscFunctionReturn(PETSC_SUCCESS);
3313: }

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

3320:   Collective on ds

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

3336:   Output Parameters:
3337: - bd       - The boundary number

3339:   Options Database Keys:
3340: + -bc_<boundary name> <num> - Overrides the boundary ids
3341: - -bc_<boundary name>_comp <num> - Overrides the boundary components

3343:   Calling Sequence of bcFunc() and bcFunc_t():
3344:   If the type is `DM_BC_ESSENTIAL`
3345: .vb
3346:   bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])
3347: .ve
3348:   If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value,
3349: .vb
3350:   bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
3351:          const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
3352:          const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
3353:          PetscReal time, const PetscReal x[], PetscScalar bcval[])
3354: .ve
3355: + dim - the spatial dimension
3356: . Nf - the number of fields
3357: . uOff - the offset into u[] and u_t[] for each field
3358: . uOff_x - the offset into u_x[] for each field
3359: . u - each field evaluated at the current point
3360: . u_t - the time derivative of each field evaluated at the current point
3361: . u_x - the gradient of each field evaluated at the current point
3362: . aOff - the offset into a[] and a_t[] for each auxiliary field
3363: . aOff_x - the offset into a_x[] for each auxiliary field
3364: . a - each auxiliary field evaluated at the current point
3365: . a_t - the time derivative of each auxiliary field evaluated at the current point
3366: . a_x - the gradient of auxiliary each field evaluated at the current point
3367: . t - current time
3368: . x - coordinates of the current point
3369: . numConstants - number of constant parameters
3370: . constants - constant parameters
3371: - bcval - output values at the current point

3373:   Level: developer

3375:   Note:
3376:   This function should only be used with `DMFOREST` currently, since labels cannot be defined before the underlying `DMPLEX` is built.

3378: .seealso: `PetscDS`, `PetscWeakForm`, `DMLabel`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSSetResidual()`, `PetscDSSetBdResidual()`
3379: @*/
3380: 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)
3381: {
3382:   DSBoundary head = ds->boundary, b;
3383:   PetscInt   n    = 0;

3385:   PetscFunctionBegin;
3393:   PetscCall(PetscNew(&b));
3394:   PetscCall(PetscStrallocpy(name, (char **)&b->name));
3395:   PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf));
3396:   PetscCall(PetscWeakFormSetNumFields(b->wf, ds->Nf));
3397:   PetscCall(PetscMalloc1(Nv, &b->values));
3398:   if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv));
3399:   PetscCall(PetscMalloc1(Nc, &b->comps));
3400:   if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc));
3401:   PetscCall(PetscStrallocpy(lname, (char **)&b->lname));
3402:   b->type   = type;
3403:   b->label  = NULL;
3404:   b->Nv     = Nv;
3405:   b->field  = field;
3406:   b->Nc     = Nc;
3407:   b->func   = bcFunc;
3408:   b->func_t = bcFunc_t;
3409:   b->ctx    = ctx;
3410:   b->next   = NULL;
3411:   /* Append to linked list so that we can preserve the order */
3412:   if (!head) ds->boundary = b;
3413:   while (head) {
3414:     if (!head->next) {
3415:       head->next = b;
3416:       head       = b;
3417:     }
3418:     head = head->next;
3419:     ++n;
3420:   }
3421:   if (bd) {
3423:     *bd = n;
3424:   }
3425:   PetscFunctionReturn(PETSC_SUCCESS);
3426: }

3428: /*@C
3429:   PetscDSUpdateBoundary - Change a boundary condition for the model. The pointwise functions are used to provide boundary values for essential boundary conditions.
3430:   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
3431:   should be performed, using the kernels from `PetscDSSetBdResidual()`.

3433:   Input Parameters:
3434: + ds       - The `PetscDS` object
3435: . bd       - The boundary condition number
3436: . type     - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
3437: . name     - The BC name
3438: . label    - The label defining constrained points
3439: . Nv       - The number of `DMLabel` ids for constrained points
3440: . values   - An array of ids for constrained points
3441: . field    - The field to constrain
3442: . Nc       - The number of constrained field components
3443: . comps    - An array of constrained component numbers
3444: . bcFunc   - A pointwise function giving boundary values
3445: . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL
3446: - ctx      - An optional user context for bcFunc

3448:   Level: developer

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

3454: .seealso: `PetscDS`, `PetscWeakForm`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSGetNumBoundary()`, `DMLabel`
3455: @*/
3456: 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)
3457: {
3458:   DSBoundary b = ds->boundary;
3459:   PetscInt   n = 0;

3461:   PetscFunctionBegin;
3463:   while (b) {
3464:     if (n == bd) break;
3465:     b = b->next;
3466:     ++n;
3467:   }
3468:   PetscCheck(b, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bd, n);
3469:   if (name) {
3470:     PetscCall(PetscFree(b->name));
3471:     PetscCall(PetscStrallocpy(name, (char **)&b->name));
3472:   }
3473:   b->type = type;
3474:   if (label) {
3475:     const char *name;

3477:     b->label = label;
3478:     PetscCall(PetscFree(b->lname));
3479:     PetscCall(PetscObjectGetName((PetscObject)label, &name));
3480:     PetscCall(PetscStrallocpy(name, (char **)&b->lname));
3481:   }
3482:   if (Nv >= 0) {
3483:     b->Nv = Nv;
3484:     PetscCall(PetscFree(b->values));
3485:     PetscCall(PetscMalloc1(Nv, &b->values));
3486:     if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv));
3487:   }
3488:   if (field >= 0) b->field = field;
3489:   if (Nc >= 0) {
3490:     b->Nc = Nc;
3491:     PetscCall(PetscFree(b->comps));
3492:     PetscCall(PetscMalloc1(Nc, &b->comps));
3493:     if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc));
3494:   }
3495:   if (bcFunc) b->func = bcFunc;
3496:   if (bcFunc_t) b->func_t = bcFunc_t;
3497:   if (ctx) b->ctx = ctx;
3498:   PetscFunctionReturn(PETSC_SUCCESS);
3499: }

3501: /*@
3502:   PetscDSGetNumBoundary - Get the number of registered BC

3504:   Input Parameters:
3505: . ds - The `PetscDS` object

3507:   Output Parameters:
3508: . numBd - The number of BC

3510:   Level: intermediate

3512: .seealso: `PetscDS`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`
3513: @*/
3514: PetscErrorCode PetscDSGetNumBoundary(PetscDS ds, PetscInt *numBd)
3515: {
3516:   DSBoundary b = ds->boundary;

3518:   PetscFunctionBegin;
3521:   *numBd = 0;
3522:   while (b) {
3523:     ++(*numBd);
3524:     b = b->next;
3525:   }
3526:   PetscFunctionReturn(PETSC_SUCCESS);
3527: }

3529: /*@C
3530:   PetscDSGetBoundary - Gets a boundary condition to the model

3532:   Input Parameters:
3533: + ds          - The `PetscDS` object
3534: - bd          - The BC number

3536:   Output Parameters:
3537: + wf       - The `PetscWeakForm` holding the pointwise functions
3538: . type     - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
3539: . name     - The BC name
3540: . label    - The label defining constrained points
3541: . Nv       - The number of `DMLabel` ids for constrained points
3542: . values   - An array of ids for constrained points
3543: . field    - The field to constrain
3544: . Nc       - The number of constrained field components
3545: . comps    - An array of constrained component numbers
3546: . bcFunc   - A pointwise function giving boundary values
3547: . bcFunc_t - A pointwise function giving the time derivative of the boundary values
3548: - ctx      - An optional user context for bcFunc

3550:   Options Database Keys:
3551: + -bc_<boundary name> <num> - Overrides the boundary ids
3552: - -bc_<boundary name>_comp <num> - Overrides the boundary components

3554:   Level: developer

3556: .seealso: `PetscDS`, `PetscWeakForm`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `DMLabel`
3557: @*/
3558: 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)
3559: {
3560:   DSBoundary b = ds->boundary;
3561:   PetscInt   n = 0;

3563:   PetscFunctionBegin;
3565:   while (b) {
3566:     if (n == bd) break;
3567:     b = b->next;
3568:     ++n;
3569:   }
3570:   PetscCheck(b, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bd, n);
3571:   if (wf) {
3573:     *wf = b->wf;
3574:   }
3575:   if (type) {
3577:     *type = b->type;
3578:   }
3579:   if (name) {
3581:     *name = b->name;
3582:   }
3583:   if (label) {
3585:     *label = b->label;
3586:   }
3587:   if (Nv) {
3589:     *Nv = b->Nv;
3590:   }
3591:   if (values) {
3593:     *values = b->values;
3594:   }
3595:   if (field) {
3597:     *field = b->field;
3598:   }
3599:   if (Nc) {
3601:     *Nc = b->Nc;
3602:   }
3603:   if (comps) {
3605:     *comps = b->comps;
3606:   }
3607:   if (func) {
3609:     *func = b->func;
3610:   }
3611:   if (func_t) {
3613:     *func_t = b->func_t;
3614:   }
3615:   if (ctx) {
3617:     *ctx = b->ctx;
3618:   }
3619:   PetscFunctionReturn(PETSC_SUCCESS);
3620: }

3622: static PetscErrorCode DSBoundaryDuplicate_Internal(DSBoundary b, DSBoundary *bNew)
3623: {
3624:   PetscFunctionBegin;
3625:   PetscCall(PetscNew(bNew));
3626:   PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &(*bNew)->wf));
3627:   PetscCall(PetscWeakFormCopy(b->wf, (*bNew)->wf));
3628:   PetscCall(PetscStrallocpy(b->name, (char **)&((*bNew)->name)));
3629:   PetscCall(PetscStrallocpy(b->lname, (char **)&((*bNew)->lname)));
3630:   (*bNew)->type  = b->type;
3631:   (*bNew)->label = b->label;
3632:   (*bNew)->Nv    = b->Nv;
3633:   PetscCall(PetscMalloc1(b->Nv, &(*bNew)->values));
3634:   PetscCall(PetscArraycpy((*bNew)->values, b->values, b->Nv));
3635:   (*bNew)->field = b->field;
3636:   (*bNew)->Nc    = b->Nc;
3637:   PetscCall(PetscMalloc1(b->Nc, &(*bNew)->comps));
3638:   PetscCall(PetscArraycpy((*bNew)->comps, b->comps, b->Nc));
3639:   (*bNew)->func   = b->func;
3640:   (*bNew)->func_t = b->func_t;
3641:   (*bNew)->ctx    = b->ctx;
3642:   PetscFunctionReturn(PETSC_SUCCESS);
3643: }

3645: /*@
3646:   PetscDSCopyBoundary - Copy all boundary condition objects to the new problem

3648:   Not collective

3650:   Input Parameters:
3651: + ds        - The source `PetscDS` object
3652: . numFields - The number of selected fields, or `PETSC_DEFAULT` for all fields
3653: - fields    - The selected fields, or NULL for all fields

3655:   Output Parameter:
3656: . newds     - The target `PetscDS`, now with a copy of the boundary conditions

3658:   Level: intermediate

3660: .seealso: `PetscDS`, `DMBoundary`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3661: @*/
3662: PetscErrorCode PetscDSCopyBoundary(PetscDS ds, PetscInt numFields, const PetscInt fields[], PetscDS newds)
3663: {
3664:   DSBoundary b, *lastnext;

3666:   PetscFunctionBegin;
3669:   if (ds == newds) PetscFunctionReturn(PETSC_SUCCESS);
3670:   PetscCall(PetscDSDestroyBoundary(newds));
3671:   lastnext = &(newds->boundary);
3672:   for (b = ds->boundary; b; b = b->next) {
3673:     DSBoundary bNew;
3674:     PetscInt   fieldNew = -1;

3676:     if (numFields > 0 && fields) {
3677:       PetscInt f;

3679:       for (f = 0; f < numFields; ++f)
3680:         if (b->field == fields[f]) break;
3681:       if (f == numFields) continue;
3682:       fieldNew = f;
3683:     }
3684:     PetscCall(DSBoundaryDuplicate_Internal(b, &bNew));
3685:     bNew->field = fieldNew < 0 ? b->field : fieldNew;
3686:     *lastnext   = bNew;
3687:     lastnext    = &(bNew->next);
3688:   }
3689:   PetscFunctionReturn(PETSC_SUCCESS);
3690: }

3692: /*@
3693:   PetscDSDestroyBoundary - Remove all `DMBoundary` objects from the `PetscDS`

3695:   Not collective

3697:   Input Parameter:
3698: . ds - The `PetscDS` object

3700:   Level: intermediate

3702: .seealso: `PetscDS`, `DMBoundary`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`
3703: @*/
3704: PetscErrorCode PetscDSDestroyBoundary(PetscDS ds)
3705: {
3706:   DSBoundary next = ds->boundary;

3708:   PetscFunctionBegin;
3709:   while (next) {
3710:     DSBoundary b = next;

3712:     next = b->next;
3713:     PetscCall(PetscWeakFormDestroy(&b->wf));
3714:     PetscCall(PetscFree(b->name));
3715:     PetscCall(PetscFree(b->lname));
3716:     PetscCall(PetscFree(b->values));
3717:     PetscCall(PetscFree(b->comps));
3718:     PetscCall(PetscFree(b));
3719:   }
3720:   PetscFunctionReturn(PETSC_SUCCESS);
3721: }

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

3726:   Not collective

3728:   Input Parameters:
3729: + prob - The `PetscDS` object
3730: . numFields - Number of new fields
3731: - fields - Old field number for each new field

3733:   Output Parameter:
3734: . newprob - The `PetscDS` copy

3736:   Level: intermediate

3738: .seealso: `PetscDS`, `PetscDSSelectEquations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3739: @*/
3740: PetscErrorCode PetscDSSelectDiscretizations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob)
3741: {
3742:   PetscInt Nf, Nfn, fn;

3744:   PetscFunctionBegin;
3748:   PetscCall(PetscDSGetNumFields(prob, &Nf));
3749:   PetscCall(PetscDSGetNumFields(newprob, &Nfn));
3750:   numFields = numFields < 0 ? Nf : numFields;
3751:   for (fn = 0; fn < numFields; ++fn) {
3752:     const PetscInt f = fields ? fields[fn] : fn;
3753:     PetscObject    disc;

3755:     if (f >= Nf) continue;
3756:     PetscCall(PetscDSGetDiscretization(prob, f, &disc));
3757:     PetscCall(PetscDSSetDiscretization(newprob, fn, disc));
3758:   }
3759:   PetscFunctionReturn(PETSC_SUCCESS);
3760: }

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

3765:   Not collective

3767:   Input Parameters:
3768: + prob - The `PetscDS` object
3769: . numFields - Number of new fields
3770: - fields - Old field number for each new field

3772:   Output Parameter:
3773: . newprob - The `PetscDS` copy

3775:   Level: intermediate

3777: .seealso: `PetscDS`, `PetscDSSelectDiscretizations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3778: @*/
3779: PetscErrorCode PetscDSSelectEquations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob)
3780: {
3781:   PetscInt Nf, Nfn, fn, gn;

3783:   PetscFunctionBegin;
3787:   PetscCall(PetscDSGetNumFields(prob, &Nf));
3788:   PetscCall(PetscDSGetNumFields(newprob, &Nfn));
3789:   PetscCheck(numFields <= Nfn, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_SIZ, "Number of fields %" PetscInt_FMT " to transfer must not be greater then the total number of fields %" PetscInt_FMT, numFields, Nfn);
3790:   for (fn = 0; fn < numFields; ++fn) {
3791:     const PetscInt   f = fields ? fields[fn] : fn;
3792:     PetscPointFunc   obj;
3793:     PetscPointFunc   f0, f1;
3794:     PetscBdPointFunc f0Bd, f1Bd;
3795:     PetscRiemannFunc r;

3797:     if (f >= Nf) continue;
3798:     PetscCall(PetscDSGetObjective(prob, f, &obj));
3799:     PetscCall(PetscDSGetResidual(prob, f, &f0, &f1));
3800:     PetscCall(PetscDSGetBdResidual(prob, f, &f0Bd, &f1Bd));
3801:     PetscCall(PetscDSGetRiemannSolver(prob, f, &r));
3802:     PetscCall(PetscDSSetObjective(newprob, fn, obj));
3803:     PetscCall(PetscDSSetResidual(newprob, fn, f0, f1));
3804:     PetscCall(PetscDSSetBdResidual(newprob, fn, f0Bd, f1Bd));
3805:     PetscCall(PetscDSSetRiemannSolver(newprob, fn, r));
3806:     for (gn = 0; gn < numFields; ++gn) {
3807:       const PetscInt  g = fields ? fields[gn] : gn;
3808:       PetscPointJac   g0, g1, g2, g3;
3809:       PetscPointJac   g0p, g1p, g2p, g3p;
3810:       PetscBdPointJac g0Bd, g1Bd, g2Bd, g3Bd;

3812:       if (g >= Nf) continue;
3813:       PetscCall(PetscDSGetJacobian(prob, f, g, &g0, &g1, &g2, &g3));
3814:       PetscCall(PetscDSGetJacobianPreconditioner(prob, f, g, &g0p, &g1p, &g2p, &g3p));
3815:       PetscCall(PetscDSGetBdJacobian(prob, f, g, &g0Bd, &g1Bd, &g2Bd, &g3Bd));
3816:       PetscCall(PetscDSSetJacobian(newprob, fn, gn, g0, g1, g2, g3));
3817:       PetscCall(PetscDSSetJacobianPreconditioner(newprob, fn, gn, g0p, g1p, g2p, g3p));
3818:       PetscCall(PetscDSSetBdJacobian(newprob, fn, gn, g0Bd, g1Bd, g2Bd, g3Bd));
3819:     }
3820:   }
3821:   PetscFunctionReturn(PETSC_SUCCESS);
3822: }

3824: /*@
3825:   PetscDSCopyEquations - Copy all pointwise function pointers to another `PetscDS`

3827:   Not collective

3829:   Input Parameter:
3830: . prob - The `PetscDS` object

3832:   Output Parameter:
3833: . newprob - The `PetscDS` copy

3835:   Level: intermediate

3837: .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3838: @*/
3839: PetscErrorCode PetscDSCopyEquations(PetscDS prob, PetscDS newprob)
3840: {
3841:   PetscWeakForm wf, newwf;
3842:   PetscInt      Nf, Ng;

3844:   PetscFunctionBegin;
3847:   PetscCall(PetscDSGetNumFields(prob, &Nf));
3848:   PetscCall(PetscDSGetNumFields(newprob, &Ng));
3849:   PetscCheck(Nf == Ng, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_SIZ, "Number of fields must match %" PetscInt_FMT " != %" PetscInt_FMT, Nf, Ng);
3850:   PetscCall(PetscDSGetWeakForm(prob, &wf));
3851:   PetscCall(PetscDSGetWeakForm(newprob, &newwf));
3852:   PetscCall(PetscWeakFormCopy(wf, newwf));
3853:   PetscFunctionReturn(PETSC_SUCCESS);
3854: }

3856: /*@
3857:   PetscDSCopyConstants - Copy all constants to another `PetscDS`

3859:   Not collective

3861:   Input Parameter:
3862: . prob - The `PetscDS` object

3864:   Output Parameter:
3865: . newprob - The `PetscDS` copy

3867:   Level: intermediate

3869: .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3870: @*/
3871: PetscErrorCode PetscDSCopyConstants(PetscDS prob, PetscDS newprob)
3872: {
3873:   PetscInt           Nc;
3874:   const PetscScalar *constants;

3876:   PetscFunctionBegin;
3879:   PetscCall(PetscDSGetConstants(prob, &Nc, &constants));
3880:   PetscCall(PetscDSSetConstants(newprob, Nc, (PetscScalar *)constants));
3881:   PetscFunctionReturn(PETSC_SUCCESS);
3882: }

3884: /*@
3885:   PetscDSCopyExactSolutions - Copy all exact solutions to another `PetscDS`

3887:   Not collective

3889:   Input Parameter:
3890: . ds - The `PetscDS` object

3892:   Output Parameter:
3893: . newds - The `PetscDS` copy

3895:   Level: intermediate

3897: .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3898: @*/
3899: PetscErrorCode PetscDSCopyExactSolutions(PetscDS ds, PetscDS newds)
3900: {
3901:   PetscSimplePointFunc sol;
3902:   void                *ctx;
3903:   PetscInt             Nf, f;

3905:   PetscFunctionBegin;
3908:   PetscCall(PetscDSGetNumFields(ds, &Nf));
3909:   for (f = 0; f < Nf; ++f) {
3910:     PetscCall(PetscDSGetExactSolution(ds, f, &sol, &ctx));
3911:     PetscCall(PetscDSSetExactSolution(newds, f, sol, ctx));
3912:     PetscCall(PetscDSGetExactSolutionTimeDerivative(ds, f, &sol, &ctx));
3913:     PetscCall(PetscDSSetExactSolutionTimeDerivative(newds, f, sol, ctx));
3914:   }
3915:   PetscFunctionReturn(PETSC_SUCCESS);
3916: }

3918: PetscErrorCode PetscDSGetHeightSubspace(PetscDS prob, PetscInt height, PetscDS *subprob)
3919: {
3920:   PetscInt dim, Nf, f;

3922:   PetscFunctionBegin;
3925:   if (height == 0) {
3926:     *subprob = prob;
3927:     PetscFunctionReturn(PETSC_SUCCESS);
3928:   }
3929:   PetscCall(PetscDSGetNumFields(prob, &Nf));
3930:   PetscCall(PetscDSGetSpatialDimension(prob, &dim));
3931:   PetscCheck(height <= dim, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_OUTOFRANGE, "DS can only handle height in [0, %" PetscInt_FMT "], not %" PetscInt_FMT, dim, height);
3932:   if (!prob->subprobs) PetscCall(PetscCalloc1(dim, &prob->subprobs));
3933:   if (!prob->subprobs[height - 1]) {
3934:     PetscInt cdim;

3936:     PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)prob), &prob->subprobs[height - 1]));
3937:     PetscCall(PetscDSGetCoordinateDimension(prob, &cdim));
3938:     PetscCall(PetscDSSetCoordinateDimension(prob->subprobs[height - 1], cdim));
3939:     for (f = 0; f < Nf; ++f) {
3940:       PetscFE      subfe;
3941:       PetscObject  obj;
3942:       PetscClassId id;

3944:       PetscCall(PetscDSGetDiscretization(prob, f, &obj));
3945:       PetscCall(PetscObjectGetClassId(obj, &id));
3946:       if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetHeightSubspace((PetscFE)obj, height, &subfe));
3947:       else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unsupported discretization type for field %" PetscInt_FMT, f);
3948:       PetscCall(PetscDSSetDiscretization(prob->subprobs[height - 1], f, (PetscObject)subfe));
3949:     }
3950:   }
3951:   *subprob = prob->subprobs[height - 1];
3952:   PetscFunctionReturn(PETSC_SUCCESS);
3953: }

3955: PetscErrorCode PetscDSGetDiscType_Internal(PetscDS ds, PetscInt f, PetscDiscType *disctype)
3956: {
3957:   PetscObject  obj;
3958:   PetscClassId id;
3959:   PetscInt     Nf;

3961:   PetscFunctionBegin;
3964:   *disctype = PETSC_DISC_NONE;
3965:   PetscCall(PetscDSGetNumFields(ds, &Nf));
3966:   PetscCheck(f < Nf, PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_SIZ, "Field %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf);
3967:   PetscCall(PetscDSGetDiscretization(ds, f, &obj));
3968:   if (obj) {
3969:     PetscCall(PetscObjectGetClassId(obj, &id));
3970:     if (id == PETSCFE_CLASSID) *disctype = PETSC_DISC_FE;
3971:     else *disctype = PETSC_DISC_FV;
3972:   }
3973:   PetscFunctionReturn(PETSC_SUCCESS);
3974: }

3976: static PetscErrorCode PetscDSDestroy_Basic(PetscDS ds)
3977: {
3978:   PetscFunctionBegin;
3979:   PetscCall(PetscFree(ds->data));
3980:   PetscFunctionReturn(PETSC_SUCCESS);
3981: }

3983: static PetscErrorCode PetscDSInitialize_Basic(PetscDS ds)
3984: {
3985:   PetscFunctionBegin;
3986:   ds->ops->setfromoptions = NULL;
3987:   ds->ops->setup          = NULL;
3988:   ds->ops->view           = NULL;
3989:   ds->ops->destroy        = PetscDSDestroy_Basic;
3990:   PetscFunctionReturn(PETSC_SUCCESS);
3991: }

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

3996:   Level: intermediate

3998: .seealso: `PetscDSType`, `PetscDSCreate()`, `PetscDSSetType()`
3999: M*/

4001: PETSC_EXTERN PetscErrorCode PetscDSCreate_Basic(PetscDS ds)
4002: {
4003:   PetscDS_Basic *b;

4005:   PetscFunctionBegin;
4007:   PetscCall(PetscNew(&b));
4008:   ds->data = b;

4010:   PetscCall(PetscDSInitialize_Basic(ds));
4011:   PetscFunctionReturn(PETSC_SUCCESS);
4012: }