Actual source code: dtds.c

petsc-3.9.4 2018-09-11
Report Typos and Errors
  1:  #include <petsc/private/petscdsimpl.h>

  3: PetscClassId PETSCDS_CLASSID = 0;

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

  8: /*@C
  9:   PetscDSRegister - Adds a new PetscDS implementation

 11:   Not Collective

 13:   Input Parameters:
 14: + name        - The name of a new user-defined creation routine
 15: - create_func - The creation routine itself

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

 20:   Sample usage:
 21: .vb
 22:     PetscDSRegister("my_ds", MyPetscDSCreate);
 23: .ve

 25:   Then, your PetscDS type can be chosen with the procedural interface via
 26: .vb
 27:     PetscDSCreate(MPI_Comm, PetscDS *);
 28:     PetscDSSetType(PetscDS, "my_ds");
 29: .ve
 30:    or at runtime via the option
 31: .vb
 32:     -petscds_type my_ds
 33: .ve

 35:   Level: advanced

 37:    Not available from Fortran

 39: .keywords: PetscDS, register
 40: .seealso: PetscDSRegisterAll(), PetscDSRegisterDestroy()

 42: @*/
 43: PetscErrorCode PetscDSRegister(const char sname[], PetscErrorCode (*function)(PetscDS))
 44: {

 48:   PetscFunctionListAdd(&PetscDSList, sname, function);
 49:   return(0);
 50: }

 52: /*@C
 53:   PetscDSSetType - Builds a particular PetscDS

 55:   Collective on PetscDS

 57:   Input Parameters:
 58: + prob - The PetscDS object
 59: - name - The kind of system

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

 64:   Level: intermediate

 66:    Not available from Fortran

 68: .keywords: PetscDS, set, type
 69: .seealso: PetscDSGetType(), PetscDSCreate()
 70: @*/
 71: PetscErrorCode PetscDSSetType(PetscDS prob, PetscDSType name)
 72: {
 73:   PetscErrorCode (*r)(PetscDS);
 74:   PetscBool      match;

 79:   PetscObjectTypeCompare((PetscObject) prob, name, &match);
 80:   if (match) return(0);

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

 86:   if (prob->ops->destroy) {
 87:     (*prob->ops->destroy)(prob);
 88:     prob->ops->destroy = NULL;
 89:   }
 90:   (*r)(prob);
 91:   PetscObjectChangeTypeName((PetscObject) prob, name);
 92:   return(0);
 93: }

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

 98:   Not Collective

100:   Input Parameter:
101: . prob  - The PetscDS

103:   Output Parameter:
104: . name - The PetscDS type name

106:   Level: intermediate

108:    Not available from Fortran

110: .keywords: PetscDS, get, type, name
111: .seealso: PetscDSSetType(), PetscDSCreate()
112: @*/
113: PetscErrorCode PetscDSGetType(PetscDS prob, PetscDSType *name)
114: {

120:   PetscDSRegisterAll();
121:   *name = ((PetscObject) prob)->type_name;
122:   return(0);
123: }

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

133:   PetscViewerGetFormat(viewer, &format);
134:   PetscViewerASCIIPrintf(viewer, "Discrete System with %d fields\n", prob->Nf);
135:   PetscViewerASCIIPushTab(viewer);
136:   for (f = 0; f < prob->Nf; ++f) {
137:     PetscObject  obj;
138:     PetscClassId id;
139:     const char  *name;
140:     PetscInt     Nc;

142:     PetscDSGetDiscretization(prob, f, &obj);
143:     PetscObjectGetClassId(obj, &id);
144:     PetscObjectGetName(obj, &name);
145:     PetscViewerASCIIPrintf(viewer, "Field %s", name ? name : "<unknown>");
146:     if (id == PETSCFE_CLASSID)      {
147:       PetscFEGetNumComponents((PetscFE) obj, &Nc);
148:       PetscViewerASCIIPrintf(viewer, " FEM");
149:     } else if (id == PETSCFV_CLASSID) {
150:       PetscFVGetNumComponents((PetscFV) obj, &Nc);
151:       PetscViewerASCIIPrintf(viewer, " FVM");
152:     }
153:     else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %D", f);
154:     if (Nc > 1) {PetscViewerASCIIPrintf(viewer, "%D components", Nc);}
155:     else        {PetscViewerASCIIPrintf(viewer, "%D component ", Nc);}
156:     if (prob->implicit[f]) {PetscViewerASCIIPrintf(viewer, " (implicit)");}
157:     else                   {PetscViewerASCIIPrintf(viewer, " (explicit)");}
158:     if (prob->adjacency[f*2+0]) {
159:       if (prob->adjacency[f*2+1]) {PetscViewerASCIIPrintf(viewer, " (adj FVM++)");}
160:       else                        {PetscViewerASCIIPrintf(viewer, " (adj FVM)");}
161:     } else {
162:       if (prob->adjacency[f*2+1]) {PetscViewerASCIIPrintf(viewer, " (adj FEM)");}
163:       else                        {PetscViewerASCIIPrintf(viewer, " (adj FUNKY)");}
164:     }
165:     PetscViewerASCIIPrintf(viewer, "\n");
166:     PetscViewerASCIIPushTab(viewer);
167:     if (id == PETSCFE_CLASSID)      {PetscFEView((PetscFE) obj, viewer);}
168:     else if (id == PETSCFV_CLASSID) {PetscFVView((PetscFV) obj, viewer);}
169:     PetscViewerASCIIPopTab(viewer);
170:   }
171:   PetscDSGetConstants(prob, &numConstants, &constants);
172:   if (numConstants) {
173:     PetscViewerASCIIPrintf(viewer, "%D constants\n", numConstants);
174:     PetscViewerASCIIPushTab(viewer);
175:     for (f = 0; f < numConstants; ++f) {PetscViewerASCIIPrintf(viewer, "%g\n", (double) PetscRealPart(constants[f]));}
176:     PetscViewerASCIIPopTab(viewer);
177:   }
178:   PetscViewerASCIIPopTab(viewer);
179:   return(0);
180: }

182: /*@C
183:   PetscDSView - Views a PetscDS

185:   Collective on PetscDS

187:   Input Parameter:
188: + prob - the PetscDS object to view
189: - v  - the viewer

191:   Level: developer

193: .seealso PetscDSDestroy()
194: @*/
195: PetscErrorCode PetscDSView(PetscDS prob, PetscViewer v)
196: {
197:   PetscBool      iascii;

202:   if (!v) {PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) prob), &v);}
204:   PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &iascii);
205:   if (iascii) {PetscDSView_Ascii(prob, v);}
206:   if (prob->ops->view) {(*prob->ops->view)(prob, v);}
207:   return(0);
208: }

210: /*@
211:   PetscDSSetFromOptions - sets parameters in a PetscDS from the options database

213:   Collective on PetscDS

215:   Input Parameter:
216: . prob - the PetscDS object to set options for

218:   Options Database:

220:   Level: developer

222: .seealso PetscDSView()
223: @*/
224: PetscErrorCode PetscDSSetFromOptions(PetscDS prob)
225: {
226:   DSBoundary     b;
227:   const char    *defaultType;
228:   char           name[256];
229:   PetscBool      flg;

234:   if (!((PetscObject) prob)->type_name) {
235:     defaultType = PETSCDSBASIC;
236:   } else {
237:     defaultType = ((PetscObject) prob)->type_name;
238:   }
239:   PetscDSRegisterAll();

241:   PetscObjectOptionsBegin((PetscObject) prob);
242:   for (b = prob->boundary; b; b = b->next) {
243:     char       optname[1024];
244:     PetscInt   ids[1024], len = 1024;
245:     PetscBool  flg;

247:     PetscSNPrintf(optname, sizeof(optname), "-bc_%s", b->name);
248:     PetscMemzero(ids, sizeof(ids));
249:     PetscOptionsIntArray(optname, "List of boundary IDs", "", ids, &len, &flg);
250:     if (flg) {
251:       b->numids = len;
252:       PetscFree(b->ids);
253:       PetscMalloc1(len, &b->ids);
254:       PetscMemcpy(b->ids, ids, len*sizeof(PetscInt));
255:     }
256:     len = 1024;
257:     PetscSNPrintf(optname, sizeof(optname), "-bc_%s_comp", b->name);
258:     PetscMemzero(ids, sizeof(ids));
259:     PetscOptionsIntArray(optname, "List of boundary field components", "", ids, &len, &flg);
260:     if (flg) {
261:       b->numcomps = len;
262:       PetscFree(b->comps);
263:       PetscMalloc1(len, &b->comps);
264:       PetscMemcpy(b->comps, ids, len*sizeof(PetscInt));
265:     }
266:   }
267:   PetscOptionsFList("-petscds_type", "Discrete System", "PetscDSSetType", PetscDSList, defaultType, name, 256, &flg);
268:   if (flg) {
269:     PetscDSSetType(prob, name);
270:   } else if (!((PetscObject) prob)->type_name) {
271:     PetscDSSetType(prob, defaultType);
272:   }
273:   if (prob->ops->setfromoptions) {(*prob->ops->setfromoptions)(prob);}
274:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
275:   PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) prob);
276:   PetscOptionsEnd();
277:   if (prob->Nf) {PetscDSViewFromOptions(prob, NULL, "-petscds_view");}
278:   return(0);
279: }

281: /*@C
282:   PetscDSSetUp - Construct data structures for the PetscDS

284:   Collective on PetscDS

286:   Input Parameter:
287: . prob - the PetscDS object to setup

289:   Level: developer

291: .seealso PetscDSView(), PetscDSDestroy()
292: @*/
293: PetscErrorCode PetscDSSetUp(PetscDS prob)
294: {
295:   const PetscInt Nf = prob->Nf;
296:   PetscInt       dim, dimEmbed, work, NcMax = 0, NqMax = 0, f;

301:   if (prob->setup) return(0);
302:   /* Calculate sizes */
303:   PetscDSGetSpatialDimension(prob, &dim);
304:   PetscDSGetCoordinateDimension(prob, &dimEmbed);
305:   prob->totDim = prob->totComp = 0;
306:   PetscMalloc2(Nf,&prob->Nc,Nf,&prob->Nb);
307:   PetscCalloc2(Nf+1,&prob->off,Nf+1,&prob->offDer);
308:   PetscMalloc4(Nf,&prob->basis,Nf,&prob->basisDer,Nf,&prob->basisFace,Nf,&prob->basisDerFace);
309:   for (f = 0; f < Nf; ++f) {
310:     PetscObject     obj;
311:     PetscClassId    id;
312:     PetscQuadrature q;
313:     PetscInt        Nq = 0, Nb, Nc;

315:     PetscDSGetDiscretization(prob, f, &obj);
316:     PetscObjectGetClassId(obj, &id);
317:     if (id == PETSCFE_CLASSID)      {
318:       PetscFE fe = (PetscFE) obj;

320:       PetscFEGetQuadrature(fe, &q);
321:       PetscFEGetDimension(fe, &Nb);
322:       PetscFEGetNumComponents(fe, &Nc);
323:       PetscFEGetDefaultTabulation(fe, &prob->basis[f], &prob->basisDer[f], NULL);
324:       PetscFEGetFaceTabulation(fe, &prob->basisFace[f], &prob->basisDerFace[f], NULL);
325:     } else if (id == PETSCFV_CLASSID) {
326:       PetscFV fv = (PetscFV) obj;

328:       PetscFVGetQuadrature(fv, &q);
329:       PetscFVGetNumComponents(fv, &Nc);
330:       Nb   = Nc;
331:       PetscFVGetDefaultTabulation(fv, &prob->basis[f], &prob->basisDer[f], NULL);
332:       /* TODO: should PetscFV also have face tabulation? Otherwise there will be a null pointer in prob->basisFace */
333:     } else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f);
334:     prob->Nc[f]       = Nc;
335:     prob->Nb[f]       = Nb;
336:     prob->off[f+1]    = Nc     + prob->off[f];
337:     prob->offDer[f+1] = Nc*dim + prob->offDer[f];
338:     if (q) {PetscQuadratureGetData(q, NULL, NULL, &Nq, NULL, NULL);}
339:     NqMax          = PetscMax(NqMax, Nq);
340:     NcMax          = PetscMax(NcMax, Nc);
341:     prob->totDim  += Nb;
342:     prob->totComp += Nc;
343:   }
344:   work = PetscMax(prob->totComp*dim, PetscSqr(NcMax*dim));
345:   /* Allocate works space */
346:   PetscMalloc5(prob->totComp,&prob->u,prob->totComp,&prob->u_t,prob->totComp*dim,&prob->u_x,dimEmbed,&prob->x,work,&prob->refSpaceDer);
347:   PetscMalloc6(NqMax*NcMax,&prob->f0,NqMax*NcMax*dim,&prob->f1,NqMax*NcMax*NcMax,&prob->g0,NqMax*NcMax*NcMax*dim,&prob->g1,NqMax*NcMax*NcMax*dim,&prob->g2,NqMax*NcMax*NcMax*dim*dim,&prob->g3);
348:   if (prob->ops->setup) {(*prob->ops->setup)(prob);}
349:   prob->setup = PETSC_TRUE;
350:   return(0);
351: }

353: static PetscErrorCode PetscDSDestroyStructs_Static(PetscDS prob)
354: {

358:   PetscFree2(prob->Nc,prob->Nb);
359:   PetscFree2(prob->off,prob->offDer);
360:   PetscFree4(prob->basis,prob->basisDer,prob->basisFace,prob->basisDerFace);
361:   PetscFree5(prob->u,prob->u_t,prob->u_x,prob->x,prob->refSpaceDer);
362:   PetscFree6(prob->f0,prob->f1,prob->g0,prob->g1,prob->g2,prob->g3);
363:   return(0);
364: }

366: static PetscErrorCode PetscDSEnlarge_Static(PetscDS prob, PetscInt NfNew)
367: {
368:   PetscObject      *tmpd;
369:   PetscBool        *tmpi, *tmpa;
370:   PetscPointFunc   *tmpobj, *tmpf, *tmpup;
371:   PetscPointJac    *tmpg, *tmpgp, *tmpgt;
372:   PetscBdPointFunc *tmpfbd;
373:   PetscBdPointJac  *tmpgbd;
374:   PetscRiemannFunc *tmpr;
375:   PetscSimplePointFunc *tmpexactSol;
376:   void            **tmpctx;
377:   PetscInt          Nf = prob->Nf, f, i;
378:   PetscErrorCode    ierr;

381:   if (Nf >= NfNew) return(0);
382:   prob->setup = PETSC_FALSE;
383:   PetscDSDestroyStructs_Static(prob);
384:   PetscMalloc3(NfNew, &tmpd, NfNew, &tmpi, NfNew*2, &tmpa);
385:   for (f = 0; f < Nf; ++f) {tmpd[f] = prob->disc[f]; tmpi[f] = prob->implicit[f]; for (i = 0; i < 2; ++i) tmpa[f*2+i] = prob->adjacency[f*2+i];}
386:   for (f = Nf; f < NfNew; ++f) {tmpd[f] = NULL; tmpi[f] = PETSC_TRUE; tmpa[f*2+0] = PETSC_FALSE; tmpa[f*2+1] = PETSC_TRUE;}
387:   PetscFree3(prob->disc, prob->implicit, prob->adjacency);
388:   prob->Nf        = NfNew;
389:   prob->disc      = tmpd;
390:   prob->implicit  = tmpi;
391:   prob->adjacency = tmpa;
392:   PetscCalloc7(NfNew, &tmpobj, NfNew*2, &tmpf, NfNew*NfNew*4, &tmpg, NfNew*NfNew*4, &tmpgp, NfNew*NfNew*4, &tmpgt, NfNew, &tmpr, NfNew, &tmpctx);
393:   PetscCalloc1(NfNew, &tmpup);
394:   for (f = 0; f < Nf; ++f) tmpobj[f] = prob->obj[f];
395:   for (f = 0; f < Nf*2; ++f) tmpf[f] = prob->f[f];
396:   for (f = 0; f < Nf*Nf*4; ++f) tmpg[f] = prob->g[f];
397:   for (f = 0; f < Nf*Nf*4; ++f) tmpgp[f] = prob->gp[f];
398:   for (f = 0; f < Nf; ++f) tmpr[f] = prob->r[f];
399:   for (f = 0; f < Nf; ++f) tmpup[f] = prob->update[f];
400:   for (f = 0; f < Nf; ++f) tmpctx[f] = prob->ctx[f];
401:   for (f = Nf; f < NfNew; ++f) tmpobj[f] = NULL;
402:   for (f = Nf*2; f < NfNew*2; ++f) tmpf[f] = NULL;
403:   for (f = Nf*Nf*4; f < NfNew*NfNew*4; ++f) tmpg[f] = NULL;
404:   for (f = Nf*Nf*4; f < NfNew*NfNew*4; ++f) tmpgp[f] = NULL;
405:   for (f = Nf*Nf*4; f < NfNew*NfNew*4; ++f) tmpgt[f] = NULL;
406:   for (f = Nf; f < NfNew; ++f) tmpr[f] = NULL;
407:   for (f = Nf; f < NfNew; ++f) tmpup[f] = NULL;
408:   for (f = Nf; f < NfNew; ++f) tmpctx[f] = NULL;
409:   PetscFree7(prob->obj, prob->f, prob->g, prob->gp, prob->gt, prob->r, prob->ctx);
410:   PetscFree(prob->update);
411:   prob->obj = tmpobj;
412:   prob->f   = tmpf;
413:   prob->g   = tmpg;
414:   prob->gp  = tmpgp;
415:   prob->gt  = tmpgt;
416:   prob->r   = tmpr;
417:   prob->update = tmpup;
418:   prob->ctx = tmpctx;
419:   PetscCalloc3(NfNew*2, &tmpfbd, NfNew*NfNew*4, &tmpgbd, NfNew, &tmpexactSol);
420:   for (f = 0; f < Nf*2; ++f) tmpfbd[f] = prob->fBd[f];
421:   for (f = 0; f < Nf*Nf*4; ++f) tmpgbd[f] = prob->gBd[f];
422:   for (f = 0; f < Nf; ++f) tmpexactSol[f] = prob->exactSol[f];
423:   for (f = Nf*2; f < NfNew*2; ++f) tmpfbd[f] = NULL;
424:   for (f = Nf*Nf*4; f < NfNew*NfNew*4; ++f) tmpgbd[f] = NULL;
425:   for (f = Nf; f < NfNew; ++f) tmpexactSol[f] = NULL;
426:   PetscFree3(prob->fBd, prob->gBd, prob->exactSol);
427:   prob->fBd = tmpfbd;
428:   prob->gBd = tmpgbd;
429:   prob->exactSol = tmpexactSol;
430:   return(0);
431: }

433: /*@
434:   PetscDSDestroy - Destroys a PetscDS object

436:   Collective on PetscDS

438:   Input Parameter:
439: . prob - the PetscDS object to destroy

441:   Level: developer

443: .seealso PetscDSView()
444: @*/
445: PetscErrorCode PetscDSDestroy(PetscDS *prob)
446: {
447:   PetscInt       f;
448:   DSBoundary     next;

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

455:   if (--((PetscObject)(*prob))->refct > 0) {*prob = 0; return(0);}
456:   ((PetscObject) (*prob))->refct = 0;
457:   if ((*prob)->subprobs) {
458:     PetscInt dim, d;

460:     PetscDSGetSpatialDimension(*prob, &dim);
461:     for (d = 0; d < dim; ++d) {PetscDSDestroy(&(*prob)->subprobs[d]);}
462:   }
463:   PetscFree((*prob)->subprobs);
464:   PetscDSDestroyStructs_Static(*prob);
465:   for (f = 0; f < (*prob)->Nf; ++f) {
466:     PetscObjectDereference((*prob)->disc[f]);
467:   }
468:   PetscFree3((*prob)->disc, (*prob)->implicit, (*prob)->adjacency);
469:   PetscFree7((*prob)->obj,(*prob)->f,(*prob)->g,(*prob)->gp,(*prob)->gt,(*prob)->r,(*prob)->ctx);
470:   PetscFree((*prob)->update);
471:   PetscFree3((*prob)->fBd,(*prob)->gBd,(*prob)->exactSol);
472:   if ((*prob)->ops->destroy) {(*(*prob)->ops->destroy)(*prob);}
473:   next = (*prob)->boundary;
474:   while (next) {
475:     DSBoundary b = next;

477:     next = b->next;
478:     PetscFree(b->comps);
479:     PetscFree(b->ids);
480:     PetscFree(b->name);
481:     PetscFree(b->labelname);
482:     PetscFree(b);
483:   }
484:   PetscFree((*prob)->constants);
485:   PetscHeaderDestroy(prob);
486:   return(0);
487: }

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

492:   Collective on MPI_Comm

494:   Input Parameter:
495: . comm - The communicator for the PetscDS object

497:   Output Parameter:
498: . prob - The PetscDS object

500:   Level: beginner

502: .seealso: PetscDSSetType(), PETSCDSBASIC
503: @*/
504: PetscErrorCode PetscDSCreate(MPI_Comm comm, PetscDS *prob)
505: {
506:   PetscDS   p;

511:   *prob  = NULL;
512:   PetscDSInitializePackage();

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

516:   p->Nf    = 0;
517:   p->setup = PETSC_FALSE;
518:   p->numConstants  = 0;
519:   p->constants     = NULL;
520:   p->dimEmbed      = -1;
521:   p->defaultAdj[0] = PETSC_FALSE;
522:   p->defaultAdj[1] = PETSC_TRUE;

524:   *prob = p;
525:   return(0);
526: }

528: /*@
529:   PetscDSGetNumFields - Returns the number of fields in the DS

531:   Not collective

533:   Input Parameter:
534: . prob - The PetscDS object

536:   Output Parameter:
537: . Nf - The number of fields

539:   Level: beginner

541: .seealso: PetscDSGetSpatialDimension(), PetscDSCreate()
542: @*/
543: PetscErrorCode PetscDSGetNumFields(PetscDS prob, PetscInt *Nf)
544: {
548:   *Nf = prob->Nf;
549:   return(0);
550: }

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

555:   Not collective

557:   Input Parameter:
558: . prob - The PetscDS object

560:   Output Parameter:
561: . dim - The spatial dimension

563:   Level: beginner

565: .seealso: PetscDSGetCoordinateDimension(), PetscDSGetNumFields(), PetscDSCreate()
566: @*/
567: PetscErrorCode PetscDSGetSpatialDimension(PetscDS prob, PetscInt *dim)
568: {

574:   *dim = 0;
575:   if (prob->Nf) {
576:     PetscObject  obj;
577:     PetscClassId id;

579:     PetscDSGetDiscretization(prob, 0, &obj);
580:     PetscObjectGetClassId(obj, &id);
581:     if (id == PETSCFE_CLASSID)      {PetscFEGetSpatialDimension((PetscFE) obj, dim);}
582:     else if (id == PETSCFV_CLASSID) {PetscFVGetSpatialDimension((PetscFV) obj, dim);}
583:     else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
584:   }
585:   return(0);
586: }

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

591:   Not collective

593:   Input Parameter:
594: . prob - The PetscDS object

596:   Output Parameter:
597: . dimEmbed - The coordinate dimension

599:   Level: beginner

601: .seealso: PetscDSSetCoordinateDimension(), PetscDSGetSpatialDimension(), PetscDSGetNumFields(), PetscDSCreate()
602: @*/
603: PetscErrorCode PetscDSGetCoordinateDimension(PetscDS prob, PetscInt *dimEmbed)
604: {
608:   if (prob->dimEmbed < 0) SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONGSTATE, "No coordinate dimension set for this DS");
609:   *dimEmbed = prob->dimEmbed;
610:   return(0);
611: }

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

616:   Not collective

618:   Input Parameters:
619: + prob - The PetscDS object
620: - dimEmbed - The coordinate dimension

622:   Level: beginner

624: .seealso: PetscDSGetCoordinateDimension(), PetscDSGetSpatialDimension(), PetscDSGetNumFields(), PetscDSCreate()
625: @*/
626: PetscErrorCode PetscDSSetCoordinateDimension(PetscDS prob, PetscInt dimEmbed)
627: {
630:   prob->dimEmbed = dimEmbed;
631:   return(0);
632: }

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

637:   Not collective

639:   Input Parameter:
640: . prob - The PetscDS object

642:   Output Parameter:
643: . dim - The total problem dimension

645:   Level: beginner

647: .seealso: PetscDSGetNumFields(), PetscDSCreate()
648: @*/
649: PetscErrorCode PetscDSGetTotalDimension(PetscDS prob, PetscInt *dim)
650: {

655:   PetscDSSetUp(prob);
657:   *dim = prob->totDim;
658:   return(0);
659: }

661: /*@
662:   PetscDSGetTotalComponents - Returns the total number of components in this system

664:   Not collective

666:   Input Parameter:
667: . prob - The PetscDS object

669:   Output Parameter:
670: . dim - The total number of components

672:   Level: beginner

674: .seealso: PetscDSGetNumFields(), PetscDSCreate()
675: @*/
676: PetscErrorCode PetscDSGetTotalComponents(PetscDS prob, PetscInt *Nc)
677: {

682:   PetscDSSetUp(prob);
684:   *Nc = prob->totComp;
685:   return(0);
686: }

688: /*@
689:   PetscDSGetDiscretization - Returns the discretization object for the given field

691:   Not collective

693:   Input Parameters:
694: + prob - The PetscDS object
695: - f - The field number

697:   Output Parameter:
698: . disc - The discretization object

700:   Level: beginner

702: .seealso: PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
703: @*/
704: PetscErrorCode PetscDSGetDiscretization(PetscDS prob, PetscInt f, PetscObject *disc)
705: {
709:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
710:   *disc = prob->disc[f];
711:   return(0);
712: }

714: /*@
715:   PetscDSSetDiscretization - Sets the discretization object for the given field

717:   Not collective

719:   Input Parameters:
720: + prob - The PetscDS object
721: . f - The field number
722: - disc - The discretization object

724:   Level: beginner

726: .seealso: PetscDSGetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
727: @*/
728: PetscErrorCode PetscDSSetDiscretization(PetscDS prob, PetscInt f, PetscObject disc)
729: {

735:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
736:   PetscDSEnlarge_Static(prob, f+1);
737:   if (prob->disc[f]) {PetscObjectDereference(prob->disc[f]);}
738:   prob->disc[f] = disc;
739:   PetscObjectReference(disc);
740:   {
741:     PetscClassId id;

743:     PetscObjectGetClassId(disc, &id);
744:     if (id == PETSCFE_CLASSID) {
745:       PetscDSSetImplicit(prob, f, PETSC_TRUE);
746:       PetscDSSetAdjacency(prob, f, PETSC_FALSE, PETSC_TRUE);
747:     } else if (id == PETSCFV_CLASSID) {
748:       PetscDSSetImplicit(prob, f, PETSC_FALSE);
749:       PetscDSSetAdjacency(prob, f, PETSC_TRUE, PETSC_FALSE);
750:     }
751:   }
752:   return(0);
753: }

755: /*@
756:   PetscDSAddDiscretization - Adds a discretization object

758:   Not collective

760:   Input Parameters:
761: + prob - The PetscDS object
762: - disc - The boundary discretization object

764:   Level: beginner

766: .seealso: PetscDSGetDiscretization(), PetscDSSetDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
767: @*/
768: PetscErrorCode PetscDSAddDiscretization(PetscDS prob, PetscObject disc)
769: {

773:   PetscDSSetDiscretization(prob, prob->Nf, disc);
774:   return(0);
775: }

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

780:   Not collective

782:   Input Parameters:
783: + prob - The PetscDS object
784: - f - The field number

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

789:   Level: developer

791: .seealso: PetscDSSetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
792: @*/
793: PetscErrorCode PetscDSGetImplicit(PetscDS prob, PetscInt f, PetscBool *implicit)
794: {
798:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
799:   *implicit = prob->implicit[f];
800:   return(0);
801: }

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

806:   Not collective

808:   Input Parameters:
809: + prob - The PetscDS object
810: . f - The field number
811: - implicit - The flag indicating what kind of solve to use for this field

813:   Level: developer

815: .seealso: PetscDSGetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
816: @*/
817: PetscErrorCode PetscDSSetImplicit(PetscDS prob, PetscInt f, PetscBool implicit)
818: {
821:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
822:   prob->implicit[f] = implicit;
823:   return(0);
824: }

826: /*@
827:   PetscDSGetAdjacency - Returns the flags for determining variable influence

829:   Not collective

831:   Input Parameters:
832: + prob - The PetscDS object
833: - f - The field number

835:   Output Parameter:
836: + useCone    - Flag for variable influence starting with the cone operation
837: - useClosure - Flag for variable influence using transitive closure

839:   Note: See the discussion in DMPlexGetAdjacencyUseCone() and DMPlexGetAdjacencyUseClosure()

841:   Level: developer

843: .seealso: PetscDSSetAdjacency(), DMPlexGetAdjacencyUseCone(), DMPlexGetAdjacencyUseClosure(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
844: @*/
845: PetscErrorCode PetscDSGetAdjacency(PetscDS prob, PetscInt f, PetscBool *useCone, PetscBool *useClosure)
846: {
851:   if (f < 0) {
852:     if (useCone)    *useCone    = prob->defaultAdj[0];
853:     if (useClosure) *useClosure = prob->defaultAdj[1];
854:   } else {
855:     if (f >= prob->Nf) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
856:     if (useCone)    *useCone    = prob->adjacency[f*2+0];
857:     if (useClosure) *useClosure = prob->adjacency[f*2+1];
858:   }
859:   return(0);
860: }

862: /*@
863:   PetscDSSetAdjacency - Set the flags for determining variable influence

865:   Not collective

867:   Input Parameters:
868: + prob - The PetscDS object
869: . f - The field number
870: . useCone    - Flag for variable influence starting with the cone operation
871: - useClosure - Flag for variable influence using transitive closure

873:   Note: See the discussion in DMPlexGetAdjacencyUseCone() and DMPlexGetAdjacencyUseClosure()

875:   Level: developer

877: .seealso: PetscDSGetAdjacency(), DMPlexGetAdjacencyUseCone(), DMPlexGetAdjacencyUseClosure(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
878: @*/
879: PetscErrorCode PetscDSSetAdjacency(PetscDS prob, PetscInt f, PetscBool useCone, PetscBool useClosure)
880: {
883:   if (f < 0) {
884:     prob->defaultAdj[0] = useCone;
885:     prob->defaultAdj[1] = useClosure;
886:   } else {
887:     if (f >= prob->Nf) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
888:     prob->adjacency[f*2+0] = useCone;
889:     prob->adjacency[f*2+1] = useClosure;
890:   }
891:   return(0);
892: }

894: PetscErrorCode PetscDSGetObjective(PetscDS prob, PetscInt f,
895:                                    void (**obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
896:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
897:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
898:                                                 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]))
899: {
903:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
904:   *obj = prob->obj[f];
905:   return(0);
906: }

908: PetscErrorCode PetscDSSetObjective(PetscDS prob, PetscInt f,
909:                                    void (*obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
910:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
911:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
912:                                                PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]))
913: {

919:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
920:   PetscDSEnlarge_Static(prob, f+1);
921:   prob->obj[f] = obj;
922:   return(0);
923: }

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

928:   Not collective

930:   Input Parameters:
931: + prob - The PetscDS
932: - f    - The test field number

934:   Output Parameters:
935: + f0 - integrand for the test function term
936: - f1 - integrand for the test function gradient term

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

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

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

944: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
945: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
946: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
947: $    PetscReal t, const PetscReal x[], PetscScalar f0[])

949: + dim - the spatial dimension
950: . Nf - the number of fields
951: . uOff - the offset into u[] and u_t[] for each field
952: . uOff_x - the offset into u_x[] for each field
953: . u - each field evaluated at the current point
954: . u_t - the time derivative of each field evaluated at the current point
955: . u_x - the gradient of each field evaluated at the current point
956: . aOff - the offset into a[] and a_t[] for each auxiliary field
957: . aOff_x - the offset into a_x[] for each auxiliary field
958: . a - each auxiliary field evaluated at the current point
959: . a_t - the time derivative of each auxiliary field evaluated at the current point
960: . a_x - the gradient of auxiliary each field evaluated at the current point
961: . t - current time
962: . x - coordinates of the current point
963: . numConstants - number of constant parameters
964: . constants - constant parameters
965: - f0 - output values at the current point

967:   Level: intermediate

969: .seealso: PetscDSSetResidual()
970: @*/
971: PetscErrorCode PetscDSGetResidual(PetscDS prob, PetscInt f,
972:                                   void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
973:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
974:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
975:                                               PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
976:                                   void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
977:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
978:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
979:                                               PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
980: {
983:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
986:   return(0);
987: }

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

992:   Not collective

994:   Input Parameters:
995: + prob - The PetscDS
996: . f    - The test field number
997: . f0 - integrand for the test function term
998: - f1 - integrand for the test function gradient term

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

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

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

1006: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1007: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1008: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1009: $    PetscReal t, const PetscReal x[], PetscScalar f0[])

1011: + dim - the spatial dimension
1012: . Nf - the number of fields
1013: . uOff - the offset into u[] and u_t[] for each field
1014: . uOff_x - the offset into u_x[] for each field
1015: . u - each field evaluated at the current point
1016: . u_t - the time derivative of each field evaluated at the current point
1017: . u_x - the gradient of each field evaluated at the current point
1018: . aOff - the offset into a[] and a_t[] for each auxiliary field
1019: . aOff_x - the offset into a_x[] for each auxiliary field
1020: . a - each auxiliary field evaluated at the current point
1021: . a_t - the time derivative of each auxiliary field evaluated at the current point
1022: . a_x - the gradient of auxiliary each field evaluated at the current point
1023: . t - current time
1024: . x - coordinates of the current point
1025: . numConstants - number of constant parameters
1026: . constants - constant parameters
1027: - f0 - output values at the current point

1029:   Level: intermediate

1031: .seealso: PetscDSGetResidual()
1032: @*/
1033: PetscErrorCode PetscDSSetResidual(PetscDS prob, PetscInt f,
1034:                                   void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1035:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1036:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1037:                                              PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
1038:                                   void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1039:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1040:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1041:                                              PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
1042: {

1049:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1050:   PetscDSEnlarge_Static(prob, f+1);
1051:   prob->f[f*2+0] = f0;
1052:   prob->f[f*2+1] = f1;
1053:   return(0);
1054: }

1056: /*@C
1057:   PetscDSHasJacobian - Signals that Jacobian functions have been set

1059:   Not collective

1061:   Input Parameter:
1062: . prob - The PetscDS

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

1067:   Level: intermediate

1069: .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
1070: @*/
1071: PetscErrorCode PetscDSHasJacobian(PetscDS prob, PetscBool *hasJac)
1072: {
1073:   PetscInt f, g, h;

1077:   *hasJac = PETSC_FALSE;
1078:   for (f = 0; f < prob->Nf; ++f) {
1079:     for (g = 0; g < prob->Nf; ++g) {
1080:       for (h = 0; h < 4; ++h) {
1081:         if (prob->g[(f*prob->Nf + g)*4+h]) *hasJac = PETSC_TRUE;
1082:       }
1083:     }
1084:   }
1085:   return(0);
1086: }

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

1091:   Not collective

1093:   Input Parameters:
1094: + prob - The PetscDS
1095: . f    - The test field number
1096: - g    - The field number

1098:   Output Parameters:
1099: + g0 - integrand for the test and basis function term
1100: . g1 - integrand for the test function and basis function gradient term
1101: . g2 - integrand for the test function gradient and basis function term
1102: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

1110: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1111: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1112: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1113: $    PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])

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

1134:   Level: intermediate

1136: .seealso: PetscDSSetJacobian()
1137: @*/
1138: PetscErrorCode PetscDSGetJacobian(PetscDS prob, PetscInt f, PetscInt g,
1139:                                   void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1140:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1141:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1142:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1143:                                   void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1144:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1145:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1146:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1147:                                   void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1148:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1149:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1150:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1151:                                   void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1152:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1153:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1154:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1155: {
1158:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
1159:   if ((g < 0) || (g >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, prob->Nf);
1164:   return(0);
1165: }

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

1170:   Not collective

1172:   Input Parameters:
1173: + prob - The PetscDS
1174: . f    - The test field number
1175: . g    - The field number
1176: . g0 - integrand for the test and basis function term
1177: . g1 - integrand for the test function and basis function gradient term
1178: . g2 - integrand for the test function gradient and basis function term
1179: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

1187: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1188: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1189: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1190: $    PetscReal t, const PetscReal x[], PetscScalar g0[])

1192: + dim - the spatial dimension
1193: . Nf - the number of fields
1194: . uOff - the offset into u[] and u_t[] for each field
1195: . uOff_x - the offset into u_x[] for each field
1196: . u - each field evaluated at the current point
1197: . u_t - the time derivative of each field evaluated at the current point
1198: . u_x - the gradient of each field evaluated at the current point
1199: . aOff - the offset into a[] and a_t[] for each auxiliary field
1200: . aOff_x - the offset into a_x[] for each auxiliary field
1201: . a - each auxiliary field evaluated at the current point
1202: . a_t - the time derivative of each auxiliary field evaluated at the current point
1203: . a_x - the gradient of auxiliary each field evaluated at the current point
1204: . t - current time
1205: . u_tShift - the multiplier a for dF/dU_t
1206: . x - coordinates of the current point
1207: . numConstants - number of constant parameters
1208: . constants - constant parameters
1209: - g0 - output values at the current point

1211:   Level: intermediate

1213: .seealso: PetscDSGetJacobian()
1214: @*/
1215: PetscErrorCode PetscDSSetJacobian(PetscDS prob, PetscInt f, PetscInt g,
1216:                                   void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1217:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1218:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1219:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1220:                                   void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1221:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1222:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1223:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1224:                                   void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1225:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1226:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1227:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1228:                                   void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1229:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1230:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1231:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1232: {

1241:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1242:   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
1243:   PetscDSEnlarge_Static(prob, PetscMax(f, g)+1);
1244:   prob->g[(f*prob->Nf + g)*4+0] = g0;
1245:   prob->g[(f*prob->Nf + g)*4+1] = g1;
1246:   prob->g[(f*prob->Nf + g)*4+2] = g2;
1247:   prob->g[(f*prob->Nf + g)*4+3] = g3;
1248:   return(0);
1249: }

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

1254:   Not collective

1256:   Input Parameter:
1257: . prob - The PetscDS

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

1262:   Level: intermediate

1264: .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
1265: @*/
1266: PetscErrorCode PetscDSHasJacobianPreconditioner(PetscDS prob, PetscBool *hasJacPre)
1267: {
1268:   PetscInt f, g, h;

1272:   *hasJacPre = PETSC_FALSE;
1273:   for (f = 0; f < prob->Nf; ++f) {
1274:     for (g = 0; g < prob->Nf; ++g) {
1275:       for (h = 0; h < 4; ++h) {
1276:         if (prob->gp[(f*prob->Nf + g)*4+h]) *hasJacPre = PETSC_TRUE;
1277:       }
1278:     }
1279:   }
1280:   return(0);
1281: }

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

1286:   Not collective

1288:   Input Parameters:
1289: + prob - The PetscDS
1290: . f    - The test field number
1291: - g    - The field number

1293:   Output Parameters:
1294: + g0 - integrand for the test and basis function term
1295: . g1 - integrand for the test function and basis function gradient term
1296: . g2 - integrand for the test function gradient and basis function term
1297: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

1305: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1306: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1307: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1308: $    PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])

1310: + dim - the spatial dimension
1311: . Nf - the number of fields
1312: . uOff - the offset into u[] and u_t[] for each field
1313: . uOff_x - the offset into u_x[] for each field
1314: . u - each field evaluated at the current point
1315: . u_t - the time derivative of each field evaluated at the current point
1316: . u_x - the gradient of each field evaluated at the current point
1317: . aOff - the offset into a[] and a_t[] for each auxiliary field
1318: . aOff_x - the offset into a_x[] for each auxiliary field
1319: . a - each auxiliary field evaluated at the current point
1320: . a_t - the time derivative of each auxiliary field evaluated at the current point
1321: . a_x - the gradient of auxiliary each field evaluated at the current point
1322: . t - current time
1323: . u_tShift - the multiplier a for dF/dU_t
1324: . x - coordinates of the current point
1325: . numConstants - number of constant parameters
1326: . constants - constant parameters
1327: - g0 - output values at the current point

1329:   Level: intermediate

1331: .seealso: PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
1332: @*/
1333: PetscErrorCode PetscDSGetJacobianPreconditioner(PetscDS prob, PetscInt f, PetscInt g,
1334:                                   void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1335:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1336:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1337:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1338:                                   void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1339:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1340:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1341:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1342:                                   void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1343:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1344:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1345:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1346:                                   void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1347:                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1348:                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1349:                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1350: {
1353:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
1354:   if ((g < 0) || (g >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, prob->Nf);
1359:   return(0);
1360: }

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

1365:   Not collective

1367:   Input Parameters:
1368: + prob - The PetscDS
1369: . f    - The test field number
1370: . g    - The field number
1371: . g0 - integrand for the test and basis function term
1372: . g1 - integrand for the test function and basis function gradient term
1373: . g2 - integrand for the test function gradient and basis function term
1374: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

1382: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1383: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1384: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1385: $    PetscReal t, const PetscReal x[], PetscScalar g0[])

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

1406:   Level: intermediate

1408: .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobian()
1409: @*/
1410: PetscErrorCode PetscDSSetJacobianPreconditioner(PetscDS prob, PetscInt f, PetscInt g,
1411:                                   void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1412:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1413:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1414:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1415:                                   void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1416:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1417:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1418:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1419:                                   void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1420:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1421:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1422:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1423:                                   void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1424:                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1425:                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1426:                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1427: {

1436:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1437:   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
1438:   PetscDSEnlarge_Static(prob, PetscMax(f, g)+1);
1439:   prob->gp[(f*prob->Nf + g)*4+0] = g0;
1440:   prob->gp[(f*prob->Nf + g)*4+1] = g1;
1441:   prob->gp[(f*prob->Nf + g)*4+2] = g2;
1442:   prob->gp[(f*prob->Nf + g)*4+3] = g3;
1443:   return(0);
1444: }

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

1449:   Not collective

1451:   Input Parameter:
1452: . prob - The PetscDS

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

1457:   Level: intermediate

1459: .seealso: PetscDSGetDynamicJacobian(), PetscDSSetDynamicJacobian(), PetscDSGetJacobian()
1460: @*/
1461: PetscErrorCode PetscDSHasDynamicJacobian(PetscDS prob, PetscBool *hasDynJac)
1462: {
1463:   PetscInt f, g, h;

1467:   *hasDynJac = PETSC_FALSE;
1468:   for (f = 0; f < prob->Nf; ++f) {
1469:     for (g = 0; g < prob->Nf; ++g) {
1470:       for (h = 0; h < 4; ++h) {
1471:         if (prob->gt[(f*prob->Nf + g)*4+h]) *hasDynJac = PETSC_TRUE;
1472:       }
1473:     }
1474:   }
1475:   return(0);
1476: }

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

1481:   Not collective

1483:   Input Parameters:
1484: + prob - The PetscDS
1485: . f    - The test field number
1486: - g    - The field number

1488:   Output Parameters:
1489: + g0 - integrand for the test and basis function term
1490: . g1 - integrand for the test function and basis function gradient term
1491: . g2 - integrand for the test function gradient and basis function term
1492: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

1500: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1501: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1502: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1503: $    PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])

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

1524:   Level: intermediate

1526: .seealso: PetscDSSetJacobian()
1527: @*/
1528: PetscErrorCode PetscDSGetDynamicJacobian(PetscDS prob, PetscInt f, PetscInt g,
1529:                                          void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1530:                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1531:                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1532:                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1533:                                          void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1534:                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1535:                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1536:                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1537:                                          void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1538:                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1539:                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1540:                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1541:                                          void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1542:                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1543:                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1544:                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1545: {
1548:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
1549:   if ((g < 0) || (g >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, prob->Nf);
1554:   return(0);
1555: }

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

1560:   Not collective

1562:   Input Parameters:
1563: + prob - The PetscDS
1564: . f    - The test field number
1565: . g    - The field number
1566: . g0 - integrand for the test and basis function term
1567: . g1 - integrand for the test function and basis function gradient term
1568: . g2 - integrand for the test function gradient and basis function term
1569: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

1577: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1578: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1579: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1580: $    PetscReal t, const PetscReal x[], PetscScalar g0[])

1582: + dim - the spatial dimension
1583: . Nf - the number of fields
1584: . uOff - the offset into u[] and u_t[] for each field
1585: . uOff_x - the offset into u_x[] for each field
1586: . u - each field evaluated at the current point
1587: . u_t - the time derivative of each field evaluated at the current point
1588: . u_x - the gradient of each field evaluated at the current point
1589: . aOff - the offset into a[] and a_t[] for each auxiliary field
1590: . aOff_x - the offset into a_x[] for each auxiliary field
1591: . a - each auxiliary field evaluated at the current point
1592: . a_t - the time derivative of each auxiliary field evaluated at the current point
1593: . a_x - the gradient of auxiliary each field evaluated at the current point
1594: . t - current time
1595: . u_tShift - the multiplier a for dF/dU_t
1596: . x - coordinates of the current point
1597: . numConstants - number of constant parameters
1598: . constants - constant parameters
1599: - g0 - output values at the current point

1601:   Level: intermediate

1603: .seealso: PetscDSGetJacobian()
1604: @*/
1605: PetscErrorCode PetscDSSetDynamicJacobian(PetscDS prob, PetscInt f, PetscInt g,
1606:                                          void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1607:                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1608:                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1609:                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1610:                                          void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1611:                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1612:                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1613:                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1614:                                          void (*g2)(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, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1618:                                          void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1619:                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1620:                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1621:                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1622: {

1631:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1632:   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
1633:   PetscDSEnlarge_Static(prob, PetscMax(f, g)+1);
1634:   prob->gt[(f*prob->Nf + g)*4+0] = g0;
1635:   prob->gt[(f*prob->Nf + g)*4+1] = g1;
1636:   prob->gt[(f*prob->Nf + g)*4+2] = g2;
1637:   prob->gt[(f*prob->Nf + g)*4+3] = g3;
1638:   return(0);
1639: }

1641: /*@C
1642:   PetscDSGetRiemannSolver - Returns the Riemann solver for the given field

1644:   Not collective

1646:   Input Arguments:
1647: + prob - The PetscDS object
1648: - f    - The field number

1650:   Output Argument:
1651: . r    - Riemann solver

1653:   Calling sequence for r:

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

1657: + dim  - The spatial dimension
1658: . Nf   - The number of fields
1659: . x    - The coordinates at a point on the interface
1660: . n    - The normal vector to the interface
1661: . uL   - The state vector to the left of the interface
1662: . uR   - The state vector to the right of the interface
1663: . flux - output array of flux through the interface
1664: . numConstants - number of constant parameters
1665: . constants - constant parameters
1666: - ctx  - optional user context

1668:   Level: intermediate

1670: .seealso: PetscDSSetRiemannSolver()
1671: @*/
1672: PetscErrorCode PetscDSGetRiemannSolver(PetscDS prob, PetscInt f,
1673:                                        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))
1674: {
1677:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
1679:   *r = prob->r[f];
1680:   return(0);
1681: }

1683: /*@C
1684:   PetscDSSetRiemannSolver - Sets the Riemann solver for the given field

1686:   Not collective

1688:   Input Arguments:
1689: + prob - The PetscDS object
1690: . f    - The field number
1691: - r    - Riemann solver

1693:   Calling sequence for r:

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

1697: + dim  - The spatial dimension
1698: . Nf   - The number of fields
1699: . x    - The coordinates at a point on the interface
1700: . n    - The normal vector to the interface
1701: . uL   - The state vector to the left of the interface
1702: . uR   - The state vector to the right of the interface
1703: . flux - output array of flux through the interface
1704: . numConstants - number of constant parameters
1705: . constants - constant parameters
1706: - ctx  - optional user context

1708:   Level: intermediate

1710: .seealso: PetscDSGetRiemannSolver()
1711: @*/
1712: PetscErrorCode PetscDSSetRiemannSolver(PetscDS prob, PetscInt f,
1713:                                        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))
1714: {

1720:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1721:   PetscDSEnlarge_Static(prob, f+1);
1722:   prob->r[f] = r;
1723:   return(0);
1724: }

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

1729:   Not collective

1731:   Input Parameters:
1732: + prob - The PetscDS
1733: - f    - The field number

1735:   Output Parameters:
1736: + update - update function

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

1740: $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1741: $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1742: $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1743: $        PetscReal t, const PetscReal x[], PetscScalar uNew[])

1745: + dim - the spatial dimension
1746: . Nf - the number of fields
1747: . uOff - the offset into u[] and u_t[] for each field
1748: . uOff_x - the offset into u_x[] for each field
1749: . u - each field evaluated at the current point
1750: . u_t - the time derivative of each field evaluated at the current point
1751: . u_x - the gradient of each field evaluated at the current point
1752: . aOff - the offset into a[] and a_t[] for each auxiliary field
1753: . aOff_x - the offset into a_x[] for each auxiliary field
1754: . a - each auxiliary field evaluated at the current point
1755: . a_t - the time derivative of each auxiliary field evaluated at the current point
1756: . a_x - the gradient of auxiliary each field evaluated at the current point
1757: . t - current time
1758: . x - coordinates of the current point
1759: - uNew - new value for field at the current point

1761:   Level: intermediate

1763: .seealso: PetscDSSetUpdate(), PetscDSSetResidual()
1764: @*/
1765: PetscErrorCode PetscDSGetUpdate(PetscDS prob, PetscInt f,
1766:                                   void (**update)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1767:                                                   const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1768:                                                   const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1769:                                                   PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[]))
1770: {
1773:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
1775:   return(0);
1776: }

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

1781:   Not collective

1783:   Input Parameters:
1784: + prob   - The PetscDS
1785: . f      - The field number
1786: - update - update function

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

1790: $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1791: $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1792: $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1793: $        PetscReal t, const PetscReal x[], PetscScalar uNew[])

1795: + dim - the spatial dimension
1796: . Nf - the number of fields
1797: . uOff - the offset into u[] and u_t[] for each field
1798: . uOff_x - the offset into u_x[] for each field
1799: . u - each field evaluated at the current point
1800: . u_t - the time derivative of each field evaluated at the current point
1801: . u_x - the gradient of each field evaluated at the current point
1802: . aOff - the offset into a[] and a_t[] for each auxiliary field
1803: . aOff_x - the offset into a_x[] for each auxiliary field
1804: . a - each auxiliary field evaluated at the current point
1805: . a_t - the time derivative of each auxiliary field evaluated at the current point
1806: . a_x - the gradient of auxiliary each field evaluated at the current point
1807: . t - current time
1808: . x - coordinates of the current point
1809: - uNew - new field values at the current point

1811:   Level: intermediate

1813: .seealso: PetscDSGetResidual()
1814: @*/
1815: PetscErrorCode PetscDSSetUpdate(PetscDS prob, PetscInt f,
1816:                                 void (*update)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1817:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1818:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1819:                                                PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[]))
1820: {

1826:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1827:   PetscDSEnlarge_Static(prob, f+1);
1828:   prob->update[f] = update;
1829:   return(0);
1830: }

1832: PetscErrorCode PetscDSGetContext(PetscDS prob, PetscInt f, void **ctx)
1833: {
1836:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
1838:   *ctx = prob->ctx[f];
1839:   return(0);
1840: }

1842: PetscErrorCode PetscDSSetContext(PetscDS prob, PetscInt f, void *ctx)
1843: {

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

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

1857:   Not collective

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

1863:   Output Parameters:
1864: + f0 - boundary integrand for the test function term
1865: - f1 - boundary integrand for the test function gradient term

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

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

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

1873: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1874: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1875: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1876: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])

1878: + dim - the spatial dimension
1879: . Nf - the number of fields
1880: . uOff - the offset into u[] and u_t[] for each field
1881: . uOff_x - the offset into u_x[] for each field
1882: . u - each field evaluated at the current point
1883: . u_t - the time derivative of each field evaluated at the current point
1884: . u_x - the gradient of each field evaluated at the current point
1885: . aOff - the offset into a[] and a_t[] for each auxiliary field
1886: . aOff_x - the offset into a_x[] for each auxiliary field
1887: . a - each auxiliary field evaluated at the current point
1888: . a_t - the time derivative of each auxiliary field evaluated at the current point
1889: . a_x - the gradient of auxiliary each field evaluated at the current point
1890: . t - current time
1891: . x - coordinates of the current point
1892: . n - unit normal at the current point
1893: . numConstants - number of constant parameters
1894: . constants - constant parameters
1895: - f0 - output values at the current point

1897:   Level: intermediate

1899: .seealso: PetscDSSetBdResidual()
1900: @*/
1901: PetscErrorCode PetscDSGetBdResidual(PetscDS prob, PetscInt f,
1902:                                     void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1903:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1904:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1905:                                                 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
1906:                                     void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1907:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1908:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1909:                                                 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
1910: {
1913:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
1916:   return(0);
1917: }

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

1922:   Not collective

1924:   Input Parameters:
1925: + prob - The PetscDS
1926: . f    - The test field number
1927: . f0 - boundary integrand for the test function term
1928: - f1 - boundary integrand for the test function gradient term

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

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

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

1936: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1937: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1938: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1939: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])

1941: + dim - the spatial dimension
1942: . Nf - the number of fields
1943: . uOff - the offset into u[] and u_t[] for each field
1944: . uOff_x - the offset into u_x[] for each field
1945: . u - each field evaluated at the current point
1946: . u_t - the time derivative of each field evaluated at the current point
1947: . u_x - the gradient of each field evaluated at the current point
1948: . aOff - the offset into a[] and a_t[] for each auxiliary field
1949: . aOff_x - the offset into a_x[] for each auxiliary field
1950: . a - each auxiliary field evaluated at the current point
1951: . a_t - the time derivative of each auxiliary field evaluated at the current point
1952: . a_x - the gradient of auxiliary each field evaluated at the current point
1953: . t - current time
1954: . x - coordinates of the current point
1955: . n - unit normal at the current point
1956: . numConstants - number of constant parameters
1957: . constants - constant parameters
1958: - f0 - output values at the current point

1960:   Level: intermediate

1962: .seealso: PetscDSGetBdResidual()
1963: @*/
1964: PetscErrorCode PetscDSSetBdResidual(PetscDS prob, PetscInt f,
1965:                                     void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1966:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1967:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1968:                                                PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
1969:                                     void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1970:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1971:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1972:                                                PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
1973: {

1978:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1979:   PetscDSEnlarge_Static(prob, f+1);
1982:   return(0);
1983: }

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

1988:   Not collective

1990:   Input Parameters:
1991: + prob - The PetscDS
1992: . f    - The test field number
1993: - g    - The field number

1995:   Output Parameters:
1996: + g0 - integrand for the test and basis function term
1997: . g1 - integrand for the test function and basis function gradient term
1998: . g2 - integrand for the test function gradient and basis function term
1999: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

2007: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2008: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2009: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2010: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[])

2012: + dim - the spatial dimension
2013: . Nf - the number of fields
2014: . uOff - the offset into u[] and u_t[] for each field
2015: . uOff_x - the offset into u_x[] for each field
2016: . u - each field evaluated at the current point
2017: . u_t - the time derivative of each field evaluated at the current point
2018: . u_x - the gradient of each field evaluated at the current point
2019: . aOff - the offset into a[] and a_t[] for each auxiliary field
2020: . aOff_x - the offset into a_x[] for each auxiliary field
2021: . a - each auxiliary field evaluated at the current point
2022: . a_t - the time derivative of each auxiliary field evaluated at the current point
2023: . a_x - the gradient of auxiliary each field evaluated at the current point
2024: . t - current time
2025: . u_tShift - the multiplier a for dF/dU_t
2026: . x - coordinates of the current point
2027: . n - normal at the current point
2028: . numConstants - number of constant parameters
2029: . constants - constant parameters
2030: - g0 - output values at the current point

2032:   Level: intermediate

2034: .seealso: PetscDSSetBdJacobian()
2035: @*/
2036: PetscErrorCode PetscDSGetBdJacobian(PetscDS prob, PetscInt f, PetscInt g,
2037:                                     void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2038:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2039:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2040:                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
2041:                                     void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2042:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2043:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2044:                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
2045:                                     void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2046:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2047:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2048:                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
2049:                                     void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2050:                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2051:                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2052:                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2053: {
2056:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
2057:   if ((g < 0) || (g >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, prob->Nf);
2062:   return(0);
2063: }

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

2068:   Not collective

2070:   Input Parameters:
2071: + prob - The PetscDS
2072: . f    - The test field number
2073: . g    - The field number
2074: . g0 - integrand for the test and basis function term
2075: . g1 - integrand for the test function and basis function gradient term
2076: . g2 - integrand for the test function gradient and basis function term
2077: - g3 - integrand for the test function gradient and basis function gradient term

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

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

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

2085: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2086: $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2087: $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2088: $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[])

2090: + dim - the spatial dimension
2091: . Nf - the number of fields
2092: . uOff - the offset into u[] and u_t[] for each field
2093: . uOff_x - the offset into u_x[] for each field
2094: . u - each field evaluated at the current point
2095: . u_t - the time derivative of each field evaluated at the current point
2096: . u_x - the gradient of each field evaluated at the current point
2097: . aOff - the offset into a[] and a_t[] for each auxiliary field
2098: . aOff_x - the offset into a_x[] for each auxiliary field
2099: . a - each auxiliary field evaluated at the current point
2100: . a_t - the time derivative of each auxiliary field evaluated at the current point
2101: . a_x - the gradient of auxiliary each field evaluated at the current point
2102: . t - current time
2103: . u_tShift - the multiplier a for dF/dU_t
2104: . x - coordinates of the current point
2105: . n - normal at the current point
2106: . numConstants - number of constant parameters
2107: . constants - constant parameters
2108: - g0 - output values at the current point

2110:   Level: intermediate

2112: .seealso: PetscDSGetBdJacobian()
2113: @*/
2114: PetscErrorCode PetscDSSetBdJacobian(PetscDS prob, PetscInt f, PetscInt g,
2115:                                     void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2116:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2117:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2118:                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
2119:                                     void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2120:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2121:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2122:                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
2123:                                     void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2124:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2125:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2126:                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
2127:                                     void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2128:                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2129:                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2130:                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2131: {

2140:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
2141:   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
2142:   PetscDSEnlarge_Static(prob, PetscMax(f, g)+1);
2143:   prob->gBd[(f*prob->Nf + g)*4+0] = g0;
2144:   prob->gBd[(f*prob->Nf + g)*4+1] = g1;
2145:   prob->gBd[(f*prob->Nf + g)*4+2] = g2;
2146:   prob->gBd[(f*prob->Nf + g)*4+3] = g3;
2147:   return(0);
2148: }

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

2153:   Not collective

2155:   Input Parameters:
2156: + prob - The PetscDS
2157: - f    - The test field number

2159:   Output Parameter:
2160: . exactSol - exact solution for the test field

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

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

2166: + dim - the spatial dimension
2167: . t - current time
2168: . x - coordinates of the current point
2169: . Nc - the number of field components
2170: . u - the solution field evaluated at the current point
2171: - ctx - a user context

2173:   Level: intermediate

2175: .seealso: PetscDSSetExactSolution()
2176: @*/
2177: PetscErrorCode PetscDSGetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx))
2178: {
2181:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
2183:   return(0);
2184: }

2186: /*@C
2187:   PetscDSSetExactSolution - Get the pointwise exact solution function for a given test field

2189:   Not collective

2191:   Input Parameters:
2192: + prob - The PetscDS
2193: . f    - The test field number
2194: - sol  - solution function for the test fields

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

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

2200: + dim - the spatial dimension
2201: . t - current time
2202: . x - coordinates of the current point
2203: . Nc - the number of field components
2204: . u - the solution field evaluated at the current point
2205: - ctx - a user context

2207:   Level: intermediate

2209: .seealso: PetscDSGetExactSolution()
2210: @*/
2211: PetscErrorCode PetscDSSetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx))
2212: {

2217:   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
2218:   PetscDSEnlarge_Static(prob, f+1);
2220:   return(0);
2221: }

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

2226:   Not collective

2228:   Input Parameter:
2229: . prob - The PetscDS object

2231:   Output Parameters:
2232: + numConstants - The number of constants
2233: - constants    - The array of constants, NULL if there are none

2235:   Level: intermediate

2237: .seealso: PetscDSSetConstants(), PetscDSCreate()
2238: @*/
2239: PetscErrorCode PetscDSGetConstants(PetscDS prob, PetscInt *numConstants, const PetscScalar *constants[])
2240: {
2245:   return(0);
2246: }

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

2251:   Not collective

2253:   Input Parameters:
2254: + prob         - The PetscDS object
2255: . numConstants - The number of constants
2256: - constants    - The array of constants, NULL if there are none

2258:   Level: intermediate

2260: .seealso: PetscDSGetConstants(), PetscDSCreate()
2261: @*/
2262: PetscErrorCode PetscDSSetConstants(PetscDS prob, PetscInt numConstants, PetscScalar constants[])
2263: {

2268:   if (numConstants != prob->numConstants) {
2269:     PetscFree(prob->constants);
2270:     prob->numConstants = numConstants;
2271:     if (prob->numConstants) {
2272:       PetscMalloc1(prob->numConstants, &prob->constants);
2273:     } else {
2274:       prob->constants = NULL;
2275:     }
2276:   }
2277:   if (prob->numConstants) {
2279:     PetscMemcpy(prob->constants, constants, prob->numConstants * sizeof(PetscScalar));
2280:   }
2281:   return(0);
2282: }

2284: /*@
2285:   PetscDSGetFieldIndex - Returns the index of the given field

2287:   Not collective

2289:   Input Parameters:
2290: + prob - The PetscDS object
2291: - disc - The discretization object

2293:   Output Parameter:
2294: . f - The field number

2296:   Level: beginner

2298: .seealso: PetscGetDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
2299: @*/
2300: PetscErrorCode PetscDSGetFieldIndex(PetscDS prob, PetscObject disc, PetscInt *f)
2301: {
2302:   PetscInt g;

2307:   *f = -1;
2308:   for (g = 0; g < prob->Nf; ++g) {if (disc == prob->disc[g]) break;}
2309:   if (g == prob->Nf) SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Field not found in PetscDS.");
2310:   *f = g;
2311:   return(0);
2312: }

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

2317:   Not collective

2319:   Input Parameters:
2320: + prob - The PetscDS object
2321: - f - The field number

2323:   Output Parameter:
2324: . size - The size

2326:   Level: beginner

2328: .seealso: PetscDSGetFieldOffset(), PetscDSGetNumFields(), PetscDSCreate()
2329: @*/
2330: PetscErrorCode PetscDSGetFieldSize(PetscDS prob, PetscInt f, PetscInt *size)
2331: {

2337:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
2338:   PetscDSSetUp(prob);
2339:   *size = prob->Nb[f];
2340:   return(0);
2341: }

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

2346:   Not collective

2348:   Input Parameters:
2349: + prob - The PetscDS object
2350: - f - The field number

2352:   Output Parameter:
2353: . off - The offset

2355:   Level: beginner

2357: .seealso: PetscDSGetFieldSize(), PetscDSGetNumFields(), PetscDSCreate()
2358: @*/
2359: PetscErrorCode PetscDSGetFieldOffset(PetscDS prob, PetscInt f, PetscInt *off)
2360: {
2361:   PetscInt       size, g;

2367:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
2368:   *off = 0;
2369:   for (g = 0; g < f; ++g) {
2370:     PetscDSGetFieldSize(prob, g, &size);
2371:     *off += size;
2372:   }
2373:   return(0);
2374: }

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

2379:   Not collective

2381:   Input Parameter:
2382: . prob - The PetscDS object

2384:   Output Parameter:
2385: . dimensions - The number of dimensions

2387:   Level: beginner

2389: .seealso: PetscDSGetComponentOffsets(), PetscDSGetNumFields(), PetscDSCreate()
2390: @*/
2391: PetscErrorCode PetscDSGetDimensions(PetscDS prob, PetscInt *dimensions[])
2392: {

2397:   PetscDSSetUp(prob);
2399:   *dimensions = prob->Nb;
2400:   return(0);
2401: }

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

2406:   Not collective

2408:   Input Parameter:
2409: . prob - The PetscDS object

2411:   Output Parameter:
2412: . components - The number of components

2414:   Level: beginner

2416: .seealso: PetscDSGetComponentOffsets(), PetscDSGetNumFields(), PetscDSCreate()
2417: @*/
2418: PetscErrorCode PetscDSGetComponents(PetscDS prob, PetscInt *components[])
2419: {

2424:   PetscDSSetUp(prob);
2426:   *components = prob->Nc;
2427:   return(0);
2428: }

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

2433:   Not collective

2435:   Input Parameters:
2436: + prob - The PetscDS object
2437: - f - The field number

2439:   Output Parameter:
2440: . off - The offset

2442:   Level: beginner

2444: .seealso: PetscDSGetNumFields(), PetscDSCreate()
2445: @*/
2446: PetscErrorCode PetscDSGetComponentOffset(PetscDS prob, PetscInt f, PetscInt *off)
2447: {
2451:   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
2452:   *off = prob->off[f];
2453:   return(0);
2454: }

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

2459:   Not collective

2461:   Input Parameter:
2462: . prob - The PetscDS object

2464:   Output Parameter:
2465: . offsets - The offsets

2467:   Level: beginner

2469: .seealso: PetscDSGetNumFields(), PetscDSCreate()
2470: @*/
2471: PetscErrorCode PetscDSGetComponentOffsets(PetscDS prob, PetscInt *offsets[])
2472: {
2476:   *offsets = prob->off;
2477:   return(0);
2478: }

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

2483:   Not collective

2485:   Input Parameter:
2486: . prob - The PetscDS object

2488:   Output Parameter:
2489: . offsets - The offsets

2491:   Level: beginner

2493: .seealso: PetscDSGetNumFields(), PetscDSCreate()
2494: @*/
2495: PetscErrorCode PetscDSGetComponentDerivativeOffsets(PetscDS prob, PetscInt *offsets[])
2496: {
2500:   *offsets = prob->offDer;
2501:   return(0);
2502: }

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

2507:   Not collective

2509:   Input Parameter:
2510: . prob - The PetscDS object

2512:   Output Parameters:
2513: + basis - The basis function tabulation at quadrature points
2514: - basisDer - The basis function derivative tabulation at quadrature points

2516:   Level: intermediate

2518: .seealso: PetscDSCreate()
2519: @*/
2520: PetscErrorCode PetscDSGetTabulation(PetscDS prob, PetscReal ***basis, PetscReal ***basisDer)
2521: {

2526:   PetscDSSetUp(prob);
2529:   return(0);
2530: }

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

2535:   Not collective

2537:   Input Parameter:
2538: . prob - The PetscDS object

2540:   Output Parameters:
2541: + basisFace - The basis function tabulation at quadrature points
2542: - basisDerFace - The basis function derivative tabulation at quadrature points

2544:   Level: intermediate

2546: .seealso: PetscDSGetTabulation(), PetscDSCreate()
2547: @*/
2548: PetscErrorCode PetscDSGetFaceTabulation(PetscDS prob, PetscReal ***basis, PetscReal ***basisDer)
2549: {

2554:   PetscDSSetUp(prob);
2557:   return(0);
2558: }

2560: PetscErrorCode PetscDSGetEvaluationArrays(PetscDS prob, PetscScalar **u, PetscScalar **u_t, PetscScalar **u_x)
2561: {

2566:   PetscDSSetUp(prob);
2570:   return(0);
2571: }

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

2579:   PetscDSSetUp(prob);
2586:   return(0);
2587: }

2589: PetscErrorCode PetscDSGetRefCoordArrays(PetscDS prob, PetscReal **x, PetscScalar **refSpaceDer)
2590: {

2595:   PetscDSSetUp(prob);
2598:   return(0);
2599: }

2601: /*@C
2602:   PetscDSAddBoundary - Add a boundary condition to the model

2604:   Input Parameters:
2605: + ds          - The PetscDS object
2606: . type        - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
2607: . name        - The BC name
2608: . labelname   - The label defining constrained points
2609: . field       - The field to constrain
2610: . numcomps    - The number of constrained field components
2611: . comps       - An array of constrained component numbers
2612: . bcFunc      - A pointwise function giving boundary values
2613: . numids      - The number of DMLabel ids for constrained points
2614: . ids         - An array of ids for constrained points
2615: - ctx         - An optional user context for bcFunc

2617:   Options Database Keys:
2618: + -bc_<boundary name> <num> - Overrides the boundary ids
2619: - -bc_<boundary name>_comp <num> - Overrides the boundary components

2621:   Level: developer

2623: .seealso: PetscDSGetBoundary()
2624: @*/
2625: PetscErrorCode PetscDSAddBoundary(PetscDS ds, DMBoundaryConditionType type, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(void), PetscInt numids, const PetscInt *ids, void *ctx)
2626: {
2627:   DSBoundary     b;

2632:   PetscNew(&b);
2633:   PetscStrallocpy(name, (char **) &b->name);
2634:   PetscStrallocpy(labelname, (char **) &b->labelname);
2635:   PetscMalloc1(numcomps, &b->comps);
2636:   if (numcomps) {PetscMemcpy(b->comps, comps, numcomps*sizeof(PetscInt));}
2637:   PetscMalloc1(numids, &b->ids);
2638:   if (numids) {PetscMemcpy(b->ids, ids, numids*sizeof(PetscInt));}
2639:   b->type            = type;
2640:   b->field           = field;
2641:   b->numcomps        = numcomps;
2642:   b->func            = bcFunc;
2643:   b->numids          = numids;
2644:   b->ctx             = ctx;
2645:   b->next            = ds->boundary;
2646:   ds->boundary       = b;
2647:   return(0);
2648: }

2650: /*@
2651:   PetscDSGetNumBoundary - Get the number of registered BC

2653:   Input Parameters:
2654: . ds - The PetscDS object

2656:   Output Parameters:
2657: . numBd - The number of BC

2659:   Level: intermediate

2661: .seealso: PetscDSAddBoundary(), PetscDSGetBoundary()
2662: @*/
2663: PetscErrorCode PetscDSGetNumBoundary(PetscDS ds, PetscInt *numBd)
2664: {
2665:   DSBoundary b = ds->boundary;

2670:   *numBd = 0;
2671:   while (b) {++(*numBd); b = b->next;}
2672:   return(0);
2673: }

2675: /*@C
2676:   PetscDSGetBoundary - Add a boundary condition to the model

2678:   Input Parameters:
2679: + ds          - The PetscDS object
2680: - bd          - The BC number

2682:   Output Parameters:
2683: + type        - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
2684: . name        - The BC name
2685: . labelname   - The label defining constrained points
2686: . field       - The field to constrain
2687: . numcomps    - The number of constrained field components
2688: . comps       - An array of constrained component numbers
2689: . bcFunc      - A pointwise function giving boundary values
2690: . numids      - The number of DMLabel ids for constrained points
2691: . ids         - An array of ids for constrained points
2692: - ctx         - An optional user context for bcFunc

2694:   Options Database Keys:
2695: + -bc_<boundary name> <num> - Overrides the boundary ids
2696: - -bc_<boundary name>_comp <num> - Overrides the boundary components

2698:   Level: developer

2700: .seealso: PetscDSAddBoundary()
2701: @*/
2702: PetscErrorCode PetscDSGetBoundary(PetscDS ds, PetscInt bd, DMBoundaryConditionType *type, const char **name, const char **labelname, PetscInt *field, PetscInt *numcomps, const PetscInt **comps, void (**func)(void), PetscInt *numids, const PetscInt **ids, void **ctx)
2703: {
2704:   DSBoundary b    = ds->boundary;
2705:   PetscInt   n    = 0;

2709:   while (b) {
2710:     if (n == bd) break;
2711:     b = b->next;
2712:     ++n;
2713:   }
2714:   if (!b) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n);
2715:   if (type) {
2717:     *type = b->type;
2718:   }
2719:   if (name) {
2721:     *name = b->name;
2722:   }
2723:   if (labelname) {
2725:     *labelname = b->labelname;
2726:   }
2727:   if (field) {
2729:     *field = b->field;
2730:   }
2731:   if (numcomps) {
2733:     *numcomps = b->numcomps;
2734:   }
2735:   if (comps) {
2737:     *comps = b->comps;
2738:   }
2739:   if (func) {
2741:     *func = b->func;
2742:   }
2743:   if (numids) {
2745:     *numids = b->numids;
2746:   }
2747:   if (ids) {
2749:     *ids = b->ids;
2750:   }
2751:   if (ctx) {
2753:     *ctx = b->ctx;
2754:   }
2755:   return(0);
2756: }

2758: PetscErrorCode PetscDSCopyBoundary(PetscDS probA, PetscDS probB)
2759: {
2760:   DSBoundary     b, next, *lastnext;

2766:   if (probA == probB) return(0);
2767:   next = probB->boundary;
2768:   while (next) {
2769:     DSBoundary b = next;

2771:     next = b->next;
2772:     PetscFree(b->comps);
2773:     PetscFree(b->ids);
2774:     PetscFree(b->name);
2775:     PetscFree(b->labelname);
2776:     PetscFree(b);
2777:   }
2778:   lastnext = &(probB->boundary);
2779:   for (b = probA->boundary; b; b = b->next) {
2780:     DSBoundary bNew;

2782:     PetscNew(&bNew);
2783:     bNew->numcomps = b->numcomps;
2784:     PetscMalloc1(bNew->numcomps, &bNew->comps);
2785:     PetscMemcpy(bNew->comps, b->comps, bNew->numcomps*sizeof(PetscInt));
2786:     bNew->numids = b->numids;
2787:     PetscMalloc1(bNew->numids, &bNew->ids);
2788:     PetscMemcpy(bNew->ids, b->ids, bNew->numids*sizeof(PetscInt));
2789:     PetscStrallocpy(b->labelname,(char **) &(bNew->labelname));
2790:     PetscStrallocpy(b->name,(char **) &(bNew->name));
2791:     bNew->ctx   = b->ctx;
2792:     bNew->type  = b->type;
2793:     bNew->field = b->field;
2794:     bNew->func  = b->func;

2796:     *lastnext = bNew;
2797:     lastnext = &(bNew->next);
2798:   }
2799:   return(0);
2800: }

2802: /*@
2803:   PetscDSCopyEquations - Copy all pointwise function pointers to the new problem

2805:   Not collective

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

2810:   Output Parameter:
2811: . newprob - The PetscDS copy

2813:   Level: intermediate

2815: .seealso: PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
2816: @*/
2817: PetscErrorCode PetscDSCopyEquations(PetscDS prob, PetscDS newprob)
2818: {
2819:   PetscInt       Nf, Ng, f, g;

2825:   PetscDSGetNumFields(prob, &Nf);
2826:   PetscDSGetNumFields(newprob, &Ng);
2827:   if (Nf != Ng) SETERRQ2(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_SIZ, "Number of fields must match %D != %D", Nf, Ng);
2828:   for (f = 0; f < Nf; ++f) {
2829:     PetscPointFunc   obj;
2830:     PetscPointFunc   f0, f1;
2831:     PetscPointJac    g0, g1, g2, g3;
2832:     PetscBdPointFunc f0Bd, f1Bd;
2833:     PetscBdPointJac  g0Bd, g1Bd, g2Bd, g3Bd;
2834:     PetscRiemannFunc r;

2836:     PetscDSGetObjective(prob, f, &obj);
2837:     PetscDSGetResidual(prob, f, &f0, &f1);
2838:     PetscDSGetBdResidual(prob, f, &f0Bd, &f1Bd);
2839:     PetscDSGetRiemannSolver(prob, f, &r);
2840:     PetscDSSetObjective(newprob, f, obj);
2841:     PetscDSSetResidual(newprob, f, f0, f1);
2842:     PetscDSSetBdResidual(newprob, f, f0Bd, f1Bd);
2843:     PetscDSSetRiemannSolver(newprob, f, r);
2844:     for (g = 0; g < Nf; ++g) {
2845:       PetscDSGetJacobian(prob, f, g, &g0, &g1, &g2, &g3);
2846:       PetscDSGetBdJacobian(prob, f, g, &g0Bd, &g1Bd, &g2Bd, &g3Bd);
2847:       PetscDSSetJacobian(newprob, f, g, g0, g1, g2, g3);
2848:       PetscDSSetBdJacobian(newprob, f, g, g0Bd, g1Bd, g2Bd, g3Bd);
2849:     }
2850:   }
2851:   return(0);
2852: }

2854: PetscErrorCode PetscDSGetHeightSubspace(PetscDS prob, PetscInt height, PetscDS *subprob)
2855: {
2856:   PetscInt       dim, Nf, f;

2862:   if (height == 0) {*subprob = prob; return(0);}
2863:   PetscDSGetNumFields(prob, &Nf);
2864:   PetscDSGetSpatialDimension(prob, &dim);
2865:   if (height > dim) SETERRQ2(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_OUTOFRANGE, "DS can only handle height in [0, %D], not %D", dim, height);
2866:   if (!prob->subprobs) {PetscCalloc1(dim, &prob->subprobs);}
2867:   if (!prob->subprobs[height-1]) {
2868:     PetscInt cdim;

2870:     PetscDSCreate(PetscObjectComm((PetscObject) prob), &prob->subprobs[height-1]);
2871:     PetscDSGetCoordinateDimension(prob, &cdim);
2872:     PetscDSSetCoordinateDimension(prob->subprobs[height-1], cdim);
2873:     for (f = 0; f < Nf; ++f) {
2874:       PetscFE      subfe;
2875:       PetscObject  obj;
2876:       PetscClassId id;

2878:       PetscDSGetDiscretization(prob, f, &obj);
2879:       PetscObjectGetClassId(obj, &id);
2880:       if (id == PETSCFE_CLASSID) {PetscFEGetHeightSubspace((PetscFE) obj, height, &subfe);}
2881:       else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unsupported discretization type for field %d", f);
2882:       PetscDSSetDiscretization(prob->subprobs[height-1], f, (PetscObject) subfe);
2883:     }
2884:   }
2885:   *subprob = prob->subprobs[height-1];
2886:   return(0);
2887: }

2889: static PetscErrorCode PetscDSDestroy_Basic(PetscDS prob)
2890: {
2891:   PetscErrorCode      ierr;

2894:   PetscFree(prob->data);
2895:   return(0);
2896: }

2898: static PetscErrorCode PetscDSInitialize_Basic(PetscDS prob)
2899: {
2901:   prob->ops->setfromoptions = NULL;
2902:   prob->ops->setup          = NULL;
2903:   prob->ops->view           = NULL;
2904:   prob->ops->destroy        = PetscDSDestroy_Basic;
2905:   return(0);
2906: }

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

2911:   Level: intermediate

2913: .seealso: PetscDSType, PetscDSCreate(), PetscDSSetType()
2914: M*/

2916: PETSC_EXTERN PetscErrorCode PetscDSCreate_Basic(PetscDS prob)
2917: {
2918:   PetscDS_Basic *b;
2919:   PetscErrorCode      ierr;

2923:   PetscNewLog(prob, &b);
2924:   prob->data = b;

2926:   PetscDSInitialize_Basic(prob);
2927:   return(0);
2928: }