xref: /petsc/src/dm/dt/interface/dtds.c (revision 536a8a5b170ea90d331b2eaeca24068ed5349df1)
1 #include <petsc/private/petscdsimpl.h> /*I "petscds.h" I*/
2 
3 PetscClassId PETSCDS_CLASSID = 0;
4 
5 PetscFunctionList PetscDSList              = NULL;
6 PetscBool         PetscDSRegisterAllCalled = PETSC_FALSE;
7 
8 /*@C
9   PetscDSRegister - Adds a new PetscDS implementation
10 
11   Not Collective
12 
13   Input Parameters:
14 + name        - The name of a new user-defined creation routine
15 - create_func - The creation routine itself
16 
17   Notes:
18   PetscDSRegister() may be called multiple times to add several user-defined PetscDSs
19 
20   Sample usage:
21 .vb
22     PetscDSRegister("my_ds", MyPetscDSCreate);
23 .ve
24 
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
34 
35   Level: advanced
36 
37 .keywords: PetscDS, register
38 .seealso: PetscDSRegisterAll(), PetscDSRegisterDestroy()
39 
40 @*/
41 PetscErrorCode PetscDSRegister(const char sname[], PetscErrorCode (*function)(PetscDS))
42 {
43   PetscErrorCode ierr;
44 
45   PetscFunctionBegin;
46   ierr = PetscFunctionListAdd(&PetscDSList, sname, function);CHKERRQ(ierr);
47   PetscFunctionReturn(0);
48 }
49 
50 /*@C
51   PetscDSSetType - Builds a particular PetscDS
52 
53   Collective on PetscDS
54 
55   Input Parameters:
56 + prob - The PetscDS object
57 - name - The kind of system
58 
59   Options Database Key:
60 . -petscds_type <type> - Sets the PetscDS type; use -help for a list of available types
61 
62   Level: intermediate
63 
64 .keywords: PetscDS, set, type
65 .seealso: PetscDSGetType(), PetscDSCreate()
66 @*/
67 PetscErrorCode PetscDSSetType(PetscDS prob, PetscDSType name)
68 {
69   PetscErrorCode (*r)(PetscDS);
70   PetscBool      match;
71   PetscErrorCode ierr;
72 
73   PetscFunctionBegin;
74   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
75   ierr = PetscObjectTypeCompare((PetscObject) prob, name, &match);CHKERRQ(ierr);
76   if (match) PetscFunctionReturn(0);
77 
78   ierr = PetscDSRegisterAll();CHKERRQ(ierr);
79   ierr = PetscFunctionListFind(PetscDSList, name, &r);CHKERRQ(ierr);
80   if (!r) SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDS type: %s", name);
81 
82   if (prob->ops->destroy) {
83     ierr             = (*prob->ops->destroy)(prob);CHKERRQ(ierr);
84     prob->ops->destroy = NULL;
85   }
86   ierr = (*r)(prob);CHKERRQ(ierr);
87   ierr = PetscObjectChangeTypeName((PetscObject) prob, name);CHKERRQ(ierr);
88   PetscFunctionReturn(0);
89 }
90 
91 /*@C
92   PetscDSGetType - Gets the PetscDS type name (as a string) from the object.
93 
94   Not Collective
95 
96   Input Parameter:
97 . prob  - The PetscDS
98 
99   Output Parameter:
100 . name - The PetscDS type name
101 
102   Level: intermediate
103 
104 .keywords: PetscDS, get, type, name
105 .seealso: PetscDSSetType(), PetscDSCreate()
106 @*/
107 PetscErrorCode PetscDSGetType(PetscDS prob, PetscDSType *name)
108 {
109   PetscErrorCode ierr;
110 
111   PetscFunctionBegin;
112   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
113   PetscValidPointer(name, 2);
114   ierr = PetscDSRegisterAll();CHKERRQ(ierr);
115   *name = ((PetscObject) prob)->type_name;
116   PetscFunctionReturn(0);
117 }
118 
119 static PetscErrorCode PetscDSView_Ascii(PetscDS prob, PetscViewer viewer)
120 {
121   PetscViewerFormat  format;
122   const PetscScalar *constants;
123   PetscInt           numConstants, f;
124   PetscErrorCode     ierr;
125 
126   PetscFunctionBegin;
127   ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
128   ierr = PetscViewerASCIIPrintf(viewer, "Discrete System with %d fields\n", prob->Nf);CHKERRQ(ierr);
129   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
130   for (f = 0; f < prob->Nf; ++f) {
131     PetscObject  obj;
132     PetscClassId id;
133     const char  *name;
134     PetscInt     Nc;
135 
136     ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr);
137     ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
138     ierr = PetscObjectGetName(obj, &name);CHKERRQ(ierr);
139     ierr = PetscViewerASCIIPrintf(viewer, "Field %s", name ? name : "<unknown>");CHKERRQ(ierr);
140     if (id == PETSCFE_CLASSID)      {
141       ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);
142       ierr = PetscViewerASCIIPrintf(viewer, " FEM");CHKERRQ(ierr);
143     } else if (id == PETSCFV_CLASSID) {
144       ierr = PetscFVGetNumComponents((PetscFV) obj, &Nc);CHKERRQ(ierr);
145       ierr = PetscViewerASCIIPrintf(viewer, " FVM");CHKERRQ(ierr);
146     }
147     else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %D", f);
148     if (Nc > 1) {ierr = PetscViewerASCIIPrintf(viewer, "%D components", Nc);CHKERRQ(ierr);}
149     else        {ierr = PetscViewerASCIIPrintf(viewer, "%D component ", Nc);CHKERRQ(ierr);}
150     if (prob->implicit[f]) {ierr = PetscViewerASCIIPrintf(viewer, " (implicit)");CHKERRQ(ierr);}
151     else                   {ierr = PetscViewerASCIIPrintf(viewer, " (explicit)");CHKERRQ(ierr);}
152     if (prob->adjacency[f*2+0]) {
153       if (prob->adjacency[f*2+1]) {ierr = PetscViewerASCIIPrintf(viewer, " (adj FVM++)");CHKERRQ(ierr);}
154       else                        {ierr = PetscViewerASCIIPrintf(viewer, " (adj FVM)");CHKERRQ(ierr);}
155     } else {
156       if (prob->adjacency[f*2+1]) {ierr = PetscViewerASCIIPrintf(viewer, " (adj FEM)");CHKERRQ(ierr);}
157       else                        {ierr = PetscViewerASCIIPrintf(viewer, " (adj FUNKY)");CHKERRQ(ierr);}
158     }
159     ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr);
160     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
161       if (id == PETSCFE_CLASSID)      {ierr = PetscFEView((PetscFE) obj, viewer);CHKERRQ(ierr);}
162       else if (id == PETSCFV_CLASSID) {ierr = PetscFVView((PetscFV) obj, viewer);CHKERRQ(ierr);}
163     }
164   }
165   ierr = PetscDSGetConstants(prob, &numConstants, &constants);CHKERRQ(ierr);
166   if (numConstants) {
167     ierr = PetscViewerASCIIPrintf(viewer, "%D constants\n", numConstants);CHKERRQ(ierr);
168     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
169     for (f = 0; f < numConstants; ++f) {ierr = PetscViewerASCIIPrintf(viewer, "%g\n", (double) PetscRealPart(constants[f]));CHKERRQ(ierr);}
170     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
171   }
172   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
173   PetscFunctionReturn(0);
174 }
175 
176 /*@C
177   PetscDSView - Views a PetscDS
178 
179   Collective on PetscDS
180 
181   Input Parameter:
182 + prob - the PetscDS object to view
183 - v  - the viewer
184 
185   Level: developer
186 
187 .seealso PetscDSDestroy()
188 @*/
189 PetscErrorCode PetscDSView(PetscDS prob, PetscViewer v)
190 {
191   PetscBool      iascii;
192   PetscErrorCode ierr;
193 
194   PetscFunctionBegin;
195   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
196   if (!v) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) prob), &v);CHKERRQ(ierr);}
197   else    {PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2);}
198   ierr = PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
199   if (iascii) {ierr = PetscDSView_Ascii(prob, v);CHKERRQ(ierr);}
200   if (prob->ops->view) {ierr = (*prob->ops->view)(prob, v);CHKERRQ(ierr);}
201   PetscFunctionReturn(0);
202 }
203 
204 /*@
205   PetscDSSetFromOptions - sets parameters in a PetscDS from the options database
206 
207   Collective on PetscDS
208 
209   Input Parameter:
210 . prob - the PetscDS object to set options for
211 
212   Options Database:
213 
214   Level: developer
215 
216 .seealso PetscDSView()
217 @*/
218 PetscErrorCode PetscDSSetFromOptions(PetscDS prob)
219 {
220   DSBoundary     b;
221   const char    *defaultType;
222   char           name[256];
223   PetscBool      flg;
224   PetscErrorCode ierr;
225 
226   PetscFunctionBegin;
227   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
228   if (!((PetscObject) prob)->type_name) {
229     defaultType = PETSCDSBASIC;
230   } else {
231     defaultType = ((PetscObject) prob)->type_name;
232   }
233   ierr = PetscDSRegisterAll();CHKERRQ(ierr);
234 
235   ierr = PetscObjectOptionsBegin((PetscObject) prob);CHKERRQ(ierr);
236   for (b = prob->boundary; b; b = b->next) {
237     char       optname[1024];
238     PetscInt   ids[1024], len = 1024;
239     PetscBool  flg;
240 
241     ierr = PetscSNPrintf(optname, sizeof(optname), "-bc_%s", b->name);CHKERRQ(ierr);
242     ierr = PetscMemzero(ids, sizeof(ids));CHKERRQ(ierr);
243     ierr = PetscOptionsIntArray(optname, "List of boundary IDs", "", ids, &len, &flg);CHKERRQ(ierr);
244     if (flg) {
245       b->numids = len;
246       ierr = PetscFree(b->ids);CHKERRQ(ierr);
247       ierr = PetscMalloc1(len, &b->ids);CHKERRQ(ierr);
248       ierr = PetscMemcpy(b->ids, ids, len*sizeof(PetscInt));CHKERRQ(ierr);
249     }
250     len = 1024;
251     ierr = PetscSNPrintf(optname, sizeof(optname), "-bc_%s_comp", b->name);CHKERRQ(ierr);
252     ierr = PetscMemzero(ids, sizeof(ids));CHKERRQ(ierr);
253     ierr = PetscOptionsIntArray(optname, "List of boundary field components", "", ids, &len, &flg);CHKERRQ(ierr);
254     if (flg) {
255       b->numcomps = len;
256       ierr = PetscFree(b->comps);CHKERRQ(ierr);
257       ierr = PetscMalloc1(len, &b->comps);CHKERRQ(ierr);
258       ierr = PetscMemcpy(b->comps, ids, len*sizeof(PetscInt));CHKERRQ(ierr);
259     }
260   }
261   ierr = PetscOptionsFList("-petscds_type", "Discrete System", "PetscDSSetType", PetscDSList, defaultType, name, 256, &flg);CHKERRQ(ierr);
262   if (flg) {
263     ierr = PetscDSSetType(prob, name);CHKERRQ(ierr);
264   } else if (!((PetscObject) prob)->type_name) {
265     ierr = PetscDSSetType(prob, defaultType);CHKERRQ(ierr);
266   }
267   if (prob->ops->setfromoptions) {ierr = (*prob->ops->setfromoptions)(prob);CHKERRQ(ierr);}
268   /* process any options handlers added with PetscObjectAddOptionsHandler() */
269   ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) prob);CHKERRQ(ierr);
270   ierr = PetscOptionsEnd();CHKERRQ(ierr);
271   ierr = PetscDSViewFromOptions(prob, NULL, "-petscds_view");CHKERRQ(ierr);
272   PetscFunctionReturn(0);
273 }
274 
275 /*@C
276   PetscDSSetUp - Construct data structures for the PetscDS
277 
278   Collective on PetscDS
279 
280   Input Parameter:
281 . prob - the PetscDS object to setup
282 
283   Level: developer
284 
285 .seealso PetscDSView(), PetscDSDestroy()
286 @*/
287 PetscErrorCode PetscDSSetUp(PetscDS prob)
288 {
289   const PetscInt Nf = prob->Nf;
290   PetscInt       dim, dimEmbed, work, NcMax = 0, NqMax = 0, f;
291   PetscErrorCode ierr;
292 
293   PetscFunctionBegin;
294   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
295   if (prob->setup) PetscFunctionReturn(0);
296   /* Calculate sizes */
297   ierr = PetscDSGetSpatialDimension(prob, &dim);CHKERRQ(ierr);
298   ierr = PetscDSGetCoordinateDimension(prob, &dimEmbed);CHKERRQ(ierr);
299   prob->totDim = prob->totComp = 0;
300   ierr = PetscMalloc2(Nf,&prob->Nc,Nf,&prob->Nb);CHKERRQ(ierr);
301   ierr = PetscCalloc2(Nf+1,&prob->off,Nf+1,&prob->offDer);CHKERRQ(ierr);
302   ierr = PetscMalloc4(Nf,&prob->basis,Nf,&prob->basisDer,Nf,&prob->basisFace,Nf,&prob->basisDerFace);CHKERRQ(ierr);
303   for (f = 0; f < Nf; ++f) {
304     PetscObject     obj;
305     PetscClassId    id;
306     PetscQuadrature q;
307     PetscInt        Nq = 0, Nb, Nc;
308 
309     ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr);
310     ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
311     if (id == PETSCFE_CLASSID)      {
312       PetscFE fe = (PetscFE) obj;
313 
314       ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr);
315       ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr);
316       ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr);
317       ierr = PetscFEGetDefaultTabulation(fe, &prob->basis[f], &prob->basisDer[f], NULL);CHKERRQ(ierr);
318       ierr = PetscFEGetFaceTabulation(fe, &prob->basisFace[f], &prob->basisDerFace[f], NULL);CHKERRQ(ierr);
319     } else if (id == PETSCFV_CLASSID) {
320       PetscFV fv = (PetscFV) obj;
321 
322       ierr = PetscFVGetQuadrature(fv, &q);CHKERRQ(ierr);
323       ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr);
324       Nb   = Nc;
325       ierr = PetscFVGetDefaultTabulation(fv, &prob->basis[f], &prob->basisDer[f], NULL);CHKERRQ(ierr);
326       /* TODO: should PetscFV also have face tabulation? Otherwise there will be a null pointer in prob->basisFace */
327     } else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f);
328     prob->Nc[f]       = Nc;
329     prob->Nb[f]       = Nb;
330     prob->off[f+1]    = Nc     + prob->off[f];
331     prob->offDer[f+1] = Nc*dim + prob->offDer[f];
332     if (q) {ierr = PetscQuadratureGetData(q, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr);}
333     NqMax          = PetscMax(NqMax, Nq);
334     NcMax          = PetscMax(NcMax, Nc);
335     prob->totDim  += Nb;
336     prob->totComp += Nc;
337   }
338   work = PetscMax(prob->totComp*dim, PetscSqr(NcMax*dim));
339   /* Allocate works space */
340   ierr = PetscMalloc5(prob->totComp,&prob->u,prob->totComp,&prob->u_t,prob->totComp*dim,&prob->u_x,dimEmbed,&prob->x,work,&prob->refSpaceDer);CHKERRQ(ierr);
341   ierr = 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);CHKERRQ(ierr);
342   if (prob->ops->setup) {ierr = (*prob->ops->setup)(prob);CHKERRQ(ierr);}
343   prob->setup = PETSC_TRUE;
344   PetscFunctionReturn(0);
345 }
346 
347 static PetscErrorCode PetscDSDestroyStructs_Static(PetscDS prob)
348 {
349   PetscErrorCode ierr;
350 
351   PetscFunctionBegin;
352   ierr = PetscFree2(prob->Nc,prob->Nb);CHKERRQ(ierr);
353   ierr = PetscFree2(prob->off,prob->offDer);CHKERRQ(ierr);
354   ierr = PetscFree4(prob->basis,prob->basisDer,prob->basisFace,prob->basisDerFace);CHKERRQ(ierr);
355   ierr = PetscFree5(prob->u,prob->u_t,prob->u_x,prob->x,prob->refSpaceDer);CHKERRQ(ierr);
356   ierr = PetscFree6(prob->f0,prob->f1,prob->g0,prob->g1,prob->g2,prob->g3);CHKERRQ(ierr);
357   PetscFunctionReturn(0);
358 }
359 
360 static PetscErrorCode PetscDSEnlarge_Static(PetscDS prob, PetscInt NfNew)
361 {
362   PetscObject      *tmpd;
363   PetscBool        *tmpi, *tmpa;
364   PetscPointFunc   *tmpobj, *tmpf, *tmpup;
365   PetscPointJac    *tmpg, *tmpgp, *tmpgt;
366   PetscBdPointFunc *tmpfbd;
367   PetscBdPointJac  *tmpgbd;
368   PetscRiemannFunc *tmpr;
369   PetscSimplePointFunc *tmpexactSol;
370   void            **tmpctx;
371   PetscInt          Nf = prob->Nf, f, i;
372   PetscErrorCode    ierr;
373 
374   PetscFunctionBegin;
375   if (Nf >= NfNew) PetscFunctionReturn(0);
376   prob->setup = PETSC_FALSE;
377   ierr = PetscDSDestroyStructs_Static(prob);CHKERRQ(ierr);
378   ierr = PetscMalloc3(NfNew, &tmpd, NfNew, &tmpi, NfNew*2, &tmpa);CHKERRQ(ierr);
379   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];}
380   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;}
381   ierr = PetscFree3(prob->disc, prob->implicit, prob->adjacency);CHKERRQ(ierr);
382   prob->Nf        = NfNew;
383   prob->disc      = tmpd;
384   prob->implicit  = tmpi;
385   prob->adjacency = tmpa;
386   ierr = PetscCalloc7(NfNew, &tmpobj, NfNew*2, &tmpf, NfNew*NfNew*4, &tmpg, NfNew*NfNew*4, &tmpgp, NfNew*NfNew*4, &tmpgt, NfNew, &tmpr, NfNew, &tmpctx);CHKERRQ(ierr);
387   ierr = PetscCalloc1(NfNew, &tmpup);CHKERRQ(ierr);
388   for (f = 0; f < Nf; ++f) tmpobj[f] = prob->obj[f];
389   for (f = 0; f < Nf*2; ++f) tmpf[f] = prob->f[f];
390   for (f = 0; f < Nf*Nf*4; ++f) tmpg[f] = prob->g[f];
391   for (f = 0; f < Nf*Nf*4; ++f) tmpgp[f] = prob->gp[f];
392   for (f = 0; f < Nf; ++f) tmpr[f] = prob->r[f];
393   for (f = 0; f < Nf; ++f) tmpup[f] = prob->update[f];
394   for (f = 0; f < Nf; ++f) tmpctx[f] = prob->ctx[f];
395   for (f = Nf; f < NfNew; ++f) tmpobj[f] = NULL;
396   for (f = Nf*2; f < NfNew*2; ++f) tmpf[f] = NULL;
397   for (f = Nf*Nf*4; f < NfNew*NfNew*4; ++f) tmpg[f] = NULL;
398   for (f = Nf*Nf*4; f < NfNew*NfNew*4; ++f) tmpgp[f] = NULL;
399   for (f = Nf*Nf*4; f < NfNew*NfNew*4; ++f) tmpgt[f] = NULL;
400   for (f = Nf; f < NfNew; ++f) tmpr[f] = NULL;
401   for (f = Nf; f < NfNew; ++f) tmpup[f] = NULL;
402   for (f = Nf; f < NfNew; ++f) tmpctx[f] = NULL;
403   ierr = PetscFree7(prob->obj, prob->f, prob->g, prob->gp, prob->gt, prob->r, prob->ctx);CHKERRQ(ierr);
404   ierr = PetscFree(prob->update);CHKERRQ(ierr);
405   prob->obj = tmpobj;
406   prob->f   = tmpf;
407   prob->g   = tmpg;
408   prob->gp  = tmpgp;
409   prob->gt  = tmpgt;
410   prob->r   = tmpr;
411   prob->update = tmpup;
412   prob->ctx = tmpctx;
413   ierr = PetscCalloc3(NfNew*2, &tmpfbd, NfNew*NfNew*4, &tmpgbd, NfNew, &tmpexactSol);CHKERRQ(ierr);
414   for (f = 0; f < Nf*2; ++f) tmpfbd[f] = prob->fBd[f];
415   for (f = 0; f < Nf*Nf*4; ++f) tmpgbd[f] = prob->gBd[f];
416   for (f = 0; f < Nf; ++f) tmpexactSol[f] = prob->exactSol[f];
417   for (f = Nf*2; f < NfNew*2; ++f) tmpfbd[f] = NULL;
418   for (f = Nf*Nf*4; f < NfNew*NfNew*4; ++f) tmpgbd[f] = NULL;
419   for (f = Nf; f < NfNew; ++f) tmpexactSol[f] = NULL;
420   ierr = PetscFree3(prob->fBd, prob->gBd, prob->exactSol);CHKERRQ(ierr);
421   prob->fBd = tmpfbd;
422   prob->gBd = tmpgbd;
423   prob->exactSol = tmpexactSol;
424   PetscFunctionReturn(0);
425 }
426 
427 /*@
428   PetscDSDestroy - Destroys a PetscDS object
429 
430   Collective on PetscDS
431 
432   Input Parameter:
433 . prob - the PetscDS object to destroy
434 
435   Level: developer
436 
437 .seealso PetscDSView()
438 @*/
439 PetscErrorCode PetscDSDestroy(PetscDS *prob)
440 {
441   PetscInt       f;
442   DSBoundary     next;
443   PetscErrorCode ierr;
444 
445   PetscFunctionBegin;
446   if (!*prob) PetscFunctionReturn(0);
447   PetscValidHeaderSpecific((*prob), PETSCDS_CLASSID, 1);
448 
449   if (--((PetscObject)(*prob))->refct > 0) {*prob = 0; PetscFunctionReturn(0);}
450   ((PetscObject) (*prob))->refct = 0;
451   ierr = PetscDSDestroyStructs_Static(*prob);CHKERRQ(ierr);
452   for (f = 0; f < (*prob)->Nf; ++f) {
453     ierr = PetscObjectDereference((*prob)->disc[f]);CHKERRQ(ierr);
454   }
455   ierr = PetscFree3((*prob)->disc, (*prob)->implicit, (*prob)->adjacency);CHKERRQ(ierr);
456   ierr = PetscFree7((*prob)->obj,(*prob)->f,(*prob)->g,(*prob)->gp,(*prob)->gt,(*prob)->r,(*prob)->ctx);CHKERRQ(ierr);
457   ierr = PetscFree((*prob)->update);CHKERRQ(ierr);
458   ierr = PetscFree3((*prob)->fBd,(*prob)->gBd,(*prob)->exactSol);CHKERRQ(ierr);
459   if ((*prob)->ops->destroy) {ierr = (*(*prob)->ops->destroy)(*prob);CHKERRQ(ierr);}
460   next = (*prob)->boundary;
461   while (next) {
462     DSBoundary b = next;
463 
464     next = b->next;
465     ierr = PetscFree(b->comps);CHKERRQ(ierr);
466     ierr = PetscFree(b->ids);CHKERRQ(ierr);
467     ierr = PetscFree(b->name);CHKERRQ(ierr);
468     ierr = PetscFree(b->labelname);CHKERRQ(ierr);
469     ierr = PetscFree(b);CHKERRQ(ierr);
470   }
471   ierr = PetscFree((*prob)->constants);CHKERRQ(ierr);
472   ierr = PetscHeaderDestroy(prob);CHKERRQ(ierr);
473   PetscFunctionReturn(0);
474 }
475 
476 /*@
477   PetscDSCreate - Creates an empty PetscDS object. The type can then be set with PetscDSSetType().
478 
479   Collective on MPI_Comm
480 
481   Input Parameter:
482 . comm - The communicator for the PetscDS object
483 
484   Output Parameter:
485 . prob - The PetscDS object
486 
487   Level: beginner
488 
489 .seealso: PetscDSSetType(), PETSCDSBASIC
490 @*/
491 PetscErrorCode PetscDSCreate(MPI_Comm comm, PetscDS *prob)
492 {
493   PetscDS   p;
494   PetscErrorCode ierr;
495 
496   PetscFunctionBegin;
497   PetscValidPointer(prob, 2);
498   *prob  = NULL;
499   ierr = PetscDSInitializePackage();CHKERRQ(ierr);
500 
501   ierr = PetscHeaderCreate(p, PETSCDS_CLASSID, "PetscDS", "Discrete System", "PetscDS", comm, PetscDSDestroy, PetscDSView);CHKERRQ(ierr);
502 
503   p->Nf    = 0;
504   p->setup = PETSC_FALSE;
505   p->numConstants = 0;
506   p->constants    = NULL;
507   p->dimEmbed     = -1;
508 
509   *prob = p;
510   PetscFunctionReturn(0);
511 }
512 
513 /*@
514   PetscDSGetNumFields - Returns the number of fields in the DS
515 
516   Not collective
517 
518   Input Parameter:
519 . prob - The PetscDS object
520 
521   Output Parameter:
522 . Nf - The number of fields
523 
524   Level: beginner
525 
526 .seealso: PetscDSGetSpatialDimension(), PetscDSCreate()
527 @*/
528 PetscErrorCode PetscDSGetNumFields(PetscDS prob, PetscInt *Nf)
529 {
530   PetscFunctionBegin;
531   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
532   PetscValidPointer(Nf, 2);
533   *Nf = prob->Nf;
534   PetscFunctionReturn(0);
535 }
536 
537 /*@
538   PetscDSGetSpatialDimension - Returns the spatial dimension of the DS, meaning the topological dimension of the discretizations
539 
540   Not collective
541 
542   Input Parameter:
543 . prob - The PetscDS object
544 
545   Output Parameter:
546 . dim - The spatial dimension
547 
548   Level: beginner
549 
550 .seealso: PetscDSGetCoordinateDimension(), PetscDSGetNumFields(), PetscDSCreate()
551 @*/
552 PetscErrorCode PetscDSGetSpatialDimension(PetscDS prob, PetscInt *dim)
553 {
554   PetscErrorCode ierr;
555 
556   PetscFunctionBegin;
557   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
558   PetscValidPointer(dim, 2);
559   *dim = 0;
560   if (prob->Nf) {
561     PetscObject  obj;
562     PetscClassId id;
563 
564     ierr = PetscDSGetDiscretization(prob, 0, &obj);CHKERRQ(ierr);
565     ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
566     if (id == PETSCFE_CLASSID)      {ierr = PetscFEGetSpatialDimension((PetscFE) obj, dim);CHKERRQ(ierr);}
567     else if (id == PETSCFV_CLASSID) {ierr = PetscFVGetSpatialDimension((PetscFV) obj, dim);CHKERRQ(ierr);}
568     else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
569   }
570   PetscFunctionReturn(0);
571 }
572 
573 /*@
574   PetscDSGetCoordinateDimension - Returns the coordinate dimension of the DS, meaning the dimension of the space into which the discretiaztions are embedded
575 
576   Not collective
577 
578   Input Parameter:
579 . prob - The PetscDS object
580 
581   Output Parameter:
582 . dimEmbed - The coordinate dimension
583 
584   Level: beginner
585 
586 .seealso: PetscDSSetCoordinateDimension(), PetscDSGetSpatialDimension(), PetscDSGetNumFields(), PetscDSCreate()
587 @*/
588 PetscErrorCode PetscDSGetCoordinateDimension(PetscDS prob, PetscInt *dimEmbed)
589 {
590   PetscFunctionBegin;
591   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
592   PetscValidPointer(dimEmbed, 2);
593   if (prob->dimEmbed < 0) SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONGSTATE, "No coordinate dimension set for this DS");
594   *dimEmbed = prob->dimEmbed;
595   PetscFunctionReturn(0);
596 }
597 
598 /*@
599   PetscDSSetCoordinateDimension - Set the coordinate dimension of the DS, meaning the dimension of the space into which the discretiaztions are embedded
600 
601   Not collective
602 
603   Input Parameters:
604 + prob - The PetscDS object
605 - dimEmbed - The coordinate dimension
606 
607   Level: beginner
608 
609 .seealso: PetscDSGetCoordinateDimension(), PetscDSGetSpatialDimension(), PetscDSGetNumFields(), PetscDSCreate()
610 @*/
611 PetscErrorCode PetscDSSetCoordinateDimension(PetscDS prob, PetscInt dimEmbed)
612 {
613   PetscFunctionBegin;
614   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
615   prob->dimEmbed = dimEmbed;
616   PetscFunctionReturn(0);
617 }
618 
619 /*@
620   PetscDSGetTotalDimension - Returns the total size of the approximation space for this system
621 
622   Not collective
623 
624   Input Parameter:
625 . prob - The PetscDS object
626 
627   Output Parameter:
628 . dim - The total problem dimension
629 
630   Level: beginner
631 
632 .seealso: PetscDSGetNumFields(), PetscDSCreate()
633 @*/
634 PetscErrorCode PetscDSGetTotalDimension(PetscDS prob, PetscInt *dim)
635 {
636   PetscErrorCode ierr;
637 
638   PetscFunctionBegin;
639   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
640   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
641   PetscValidPointer(dim, 2);
642   *dim = prob->totDim;
643   PetscFunctionReturn(0);
644 }
645 
646 /*@
647   PetscDSGetTotalComponents - Returns the total number of components in this system
648 
649   Not collective
650 
651   Input Parameter:
652 . prob - The PetscDS object
653 
654   Output Parameter:
655 . dim - The total number of components
656 
657   Level: beginner
658 
659 .seealso: PetscDSGetNumFields(), PetscDSCreate()
660 @*/
661 PetscErrorCode PetscDSGetTotalComponents(PetscDS prob, PetscInt *Nc)
662 {
663   PetscErrorCode ierr;
664 
665   PetscFunctionBegin;
666   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
667   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
668   PetscValidPointer(Nc, 2);
669   *Nc = prob->totComp;
670   PetscFunctionReturn(0);
671 }
672 
673 /*@
674   PetscDSGetDiscretization - Returns the discretization object for the given field
675 
676   Not collective
677 
678   Input Parameters:
679 + prob - The PetscDS object
680 - f - The field number
681 
682   Output Parameter:
683 . disc - The discretization object
684 
685   Level: beginner
686 
687 .seealso: PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
688 @*/
689 PetscErrorCode PetscDSGetDiscretization(PetscDS prob, PetscInt f, PetscObject *disc)
690 {
691   PetscFunctionBegin;
692   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
693   PetscValidPointer(disc, 3);
694   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);
695   *disc = prob->disc[f];
696   PetscFunctionReturn(0);
697 }
698 
699 /*@
700   PetscDSSetDiscretization - Sets the discretization object for the given field
701 
702   Not collective
703 
704   Input Parameters:
705 + prob - The PetscDS object
706 . f - The field number
707 - disc - The discretization object
708 
709   Level: beginner
710 
711 .seealso: PetscDSGetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
712 @*/
713 PetscErrorCode PetscDSSetDiscretization(PetscDS prob, PetscInt f, PetscObject disc)
714 {
715   PetscErrorCode ierr;
716 
717   PetscFunctionBegin;
718   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
719   PetscValidPointer(disc, 3);
720   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
721   ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr);
722   if (prob->disc[f]) {ierr = PetscObjectDereference(prob->disc[f]);CHKERRQ(ierr);}
723   prob->disc[f] = disc;
724   ierr = PetscObjectReference(disc);CHKERRQ(ierr);
725   {
726     PetscClassId id;
727 
728     ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr);
729     if (id == PETSCFV_CLASSID) {
730       prob->implicit[f]      = PETSC_FALSE;
731       prob->adjacency[f*2+0] = PETSC_TRUE;
732       prob->adjacency[f*2+1] = PETSC_FALSE;
733     }
734   }
735   PetscFunctionReturn(0);
736 }
737 
738 /*@
739   PetscDSAddDiscretization - Adds a discretization object
740 
741   Not collective
742 
743   Input Parameters:
744 + prob - The PetscDS object
745 - disc - The boundary discretization object
746 
747   Level: beginner
748 
749 .seealso: PetscDSGetDiscretization(), PetscDSSetDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
750 @*/
751 PetscErrorCode PetscDSAddDiscretization(PetscDS prob, PetscObject disc)
752 {
753   PetscErrorCode ierr;
754 
755   PetscFunctionBegin;
756   ierr = PetscDSSetDiscretization(prob, prob->Nf, disc);CHKERRQ(ierr);
757   PetscFunctionReturn(0);
758 }
759 
760 /*@
761   PetscDSGetImplicit - Returns the flag for implicit solve for this field. This is just a guide for IMEX
762 
763   Not collective
764 
765   Input Parameters:
766 + prob - The PetscDS object
767 - f - The field number
768 
769   Output Parameter:
770 . implicit - The flag indicating what kind of solve to use for this field
771 
772   Level: developer
773 
774 .seealso: PetscDSSetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
775 @*/
776 PetscErrorCode PetscDSGetImplicit(PetscDS prob, PetscInt f, PetscBool *implicit)
777 {
778   PetscFunctionBegin;
779   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
780   PetscValidPointer(implicit, 3);
781   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);
782   *implicit = prob->implicit[f];
783   PetscFunctionReturn(0);
784 }
785 
786 /*@
787   PetscDSSetImplicit - Set the flag for implicit solve for this field. This is just a guide for IMEX
788 
789   Not collective
790 
791   Input Parameters:
792 + prob - The PetscDS object
793 . f - The field number
794 - implicit - The flag indicating what kind of solve to use for this field
795 
796   Level: developer
797 
798 .seealso: PetscDSGetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
799 @*/
800 PetscErrorCode PetscDSSetImplicit(PetscDS prob, PetscInt f, PetscBool implicit)
801 {
802   PetscFunctionBegin;
803   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
804   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);
805   prob->implicit[f] = implicit;
806   PetscFunctionReturn(0);
807 }
808 
809 /*@
810   PetscDSGetAdjacency - Returns the flags for determining variable influence
811 
812   Not collective
813 
814   Input Parameters:
815 + prob - The PetscDS object
816 - f - The field number
817 
818   Output Parameter:
819 + useCone    - Flag for variable influence starting with the cone operation
820 - useClosure - Flag for variable influence using transitive closure
821 
822   Note: See the discussion in DMPlexGetAdjacencyUseCone() and DMPlexGetAdjacencyUseClosure()
823 
824   Level: developer
825 
826 .seealso: PetscDSSetAdjacency(), DMPlexGetAdjacencyUseCone(), DMPlexGetAdjacencyUseClosure(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
827 @*/
828 PetscErrorCode PetscDSGetAdjacency(PetscDS prob, PetscInt f, PetscBool *useCone, PetscBool *useClosure)
829 {
830   PetscFunctionBegin;
831   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
832   PetscValidPointer(useCone, 3);
833   PetscValidPointer(useClosure, 4);
834   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);
835   *useCone    = prob->adjacency[f*2+0];
836   *useClosure = prob->adjacency[f*2+1];
837   PetscFunctionReturn(0);
838 }
839 
840 /*@
841   PetscDSSetAdjacency - Set the flags for determining variable influence
842 
843   Not collective
844 
845   Input Parameters:
846 + prob - The PetscDS object
847 . f - The field number
848 . useCone    - Flag for variable influence starting with the cone operation
849 - useClosure - Flag for variable influence using transitive closure
850 
851   Note: See the discussion in DMPlexGetAdjacencyUseCone() and DMPlexGetAdjacencyUseClosure()
852 
853   Level: developer
854 
855 .seealso: PetscDSGetAdjacency(), DMPlexGetAdjacencyUseCone(), DMPlexGetAdjacencyUseClosure(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
856 @*/
857 PetscErrorCode PetscDSSetAdjacency(PetscDS prob, PetscInt f, PetscBool useCone, PetscBool useClosure)
858 {
859   PetscFunctionBegin;
860   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
861   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);
862   prob->adjacency[f*2+0] = useCone;
863   prob->adjacency[f*2+1] = useClosure;
864   PetscFunctionReturn(0);
865 }
866 
867 PetscErrorCode PetscDSGetObjective(PetscDS prob, PetscInt f,
868                                    void (**obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
869                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
870                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
871                                                 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]))
872 {
873   PetscFunctionBegin;
874   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
875   PetscValidPointer(obj, 2);
876   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);
877   *obj = prob->obj[f];
878   PetscFunctionReturn(0);
879 }
880 
881 PetscErrorCode PetscDSSetObjective(PetscDS prob, PetscInt f,
882                                    void (*obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
883                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
884                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
885                                                PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]))
886 {
887   PetscErrorCode ierr;
888 
889   PetscFunctionBegin;
890   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
891   if (obj) PetscValidFunction(obj, 2);
892   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
893   ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr);
894   prob->obj[f] = obj;
895   PetscFunctionReturn(0);
896 }
897 
898 /*@C
899   PetscDSGetResidual - Get the pointwise residual function for a given test field
900 
901   Not collective
902 
903   Input Parameters:
904 + prob - The PetscDS
905 - f    - The test field number
906 
907   Output Parameters:
908 + f0 - integrand for the test function term
909 - f1 - integrand for the test function gradient term
910 
911   Note: We are using a first order FEM model for the weak form:
912 
913   \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)
914 
915 The calling sequence for the callbacks f0 and f1 is given by:
916 
917 $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
918 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
919 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
920 $    PetscReal t, const PetscReal x[], PetscScalar f0[])
921 
922 + dim - the spatial dimension
923 . Nf - the number of fields
924 . uOff - the offset into u[] and u_t[] for each field
925 . uOff_x - the offset into u_x[] for each field
926 . u - each field evaluated at the current point
927 . u_t - the time derivative of each field evaluated at the current point
928 . u_x - the gradient of each field evaluated at the current point
929 . aOff - the offset into a[] and a_t[] for each auxiliary field
930 . aOff_x - the offset into a_x[] for each auxiliary field
931 . a - each auxiliary field evaluated at the current point
932 . a_t - the time derivative of each auxiliary field evaluated at the current point
933 . a_x - the gradient of auxiliary each field evaluated at the current point
934 . t - current time
935 . x - coordinates of the current point
936 . numConstants - number of constant parameters
937 . constants - constant parameters
938 - f0 - output values at the current point
939 
940   Level: intermediate
941 
942 .seealso: PetscDSSetResidual()
943 @*/
944 PetscErrorCode PetscDSGetResidual(PetscDS prob, PetscInt f,
945                                   void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
946                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
947                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
948                                               PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
949                                   void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
950                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
951                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
952                                               PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
953 {
954   PetscFunctionBegin;
955   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
956   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);
957   if (f0) {PetscValidPointer(f0, 3); *f0 = prob->f[f*2+0];}
958   if (f1) {PetscValidPointer(f1, 4); *f1 = prob->f[f*2+1];}
959   PetscFunctionReturn(0);
960 }
961 
962 /*@C
963   PetscDSSetResidual - Set the pointwise residual function for a given test field
964 
965   Not collective
966 
967   Input Parameters:
968 + prob - The PetscDS
969 . f    - The test field number
970 . f0 - integrand for the test function term
971 - f1 - integrand for the test function gradient term
972 
973   Note: We are using a first order FEM model for the weak form:
974 
975   \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)
976 
977 The calling sequence for the callbacks f0 and f1 is given by:
978 
979 $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
980 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
981 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
982 $    PetscReal t, const PetscReal x[], PetscScalar f0[])
983 
984 + dim - the spatial dimension
985 . Nf - the number of fields
986 . uOff - the offset into u[] and u_t[] for each field
987 . uOff_x - the offset into u_x[] for each field
988 . u - each field evaluated at the current point
989 . u_t - the time derivative of each field evaluated at the current point
990 . u_x - the gradient of each field evaluated at the current point
991 . aOff - the offset into a[] and a_t[] for each auxiliary field
992 . aOff_x - the offset into a_x[] for each auxiliary field
993 . a - each auxiliary field evaluated at the current point
994 . a_t - the time derivative of each auxiliary field evaluated at the current point
995 . a_x - the gradient of auxiliary each field evaluated at the current point
996 . t - current time
997 . x - coordinates of the current point
998 . numConstants - number of constant parameters
999 . constants - constant parameters
1000 - f0 - output values at the current point
1001 
1002   Level: intermediate
1003 
1004 .seealso: PetscDSGetResidual()
1005 @*/
1006 PetscErrorCode PetscDSSetResidual(PetscDS prob, PetscInt f,
1007                                   void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1008                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1009                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1010                                              PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
1011                                   void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1012                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1013                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1014                                              PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
1015 {
1016   PetscErrorCode ierr;
1017 
1018   PetscFunctionBegin;
1019   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1020   if (f0) PetscValidFunction(f0, 3);
1021   if (f1) PetscValidFunction(f1, 4);
1022   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1023   ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr);
1024   prob->f[f*2+0] = f0;
1025   prob->f[f*2+1] = f1;
1026   PetscFunctionReturn(0);
1027 }
1028 
1029 /*@C
1030   PetscDSHasJacobian - Signals that Jacobian functions have been set
1031 
1032   Not collective
1033 
1034   Input Parameter:
1035 . prob - The PetscDS
1036 
1037   Output Parameter:
1038 . hasJac - flag that pointwise function for the Jacobian has been set
1039 
1040   Level: intermediate
1041 
1042 .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
1043 @*/
1044 PetscErrorCode PetscDSHasJacobian(PetscDS prob, PetscBool *hasJac)
1045 {
1046   PetscInt f, g, h;
1047 
1048   PetscFunctionBegin;
1049   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1050   *hasJac = PETSC_FALSE;
1051   for (f = 0; f < prob->Nf; ++f) {
1052     for (g = 0; g < prob->Nf; ++g) {
1053       for (h = 0; h < 4; ++h) {
1054         if (prob->g[(f*prob->Nf + g)*4+h]) *hasJac = PETSC_TRUE;
1055       }
1056     }
1057   }
1058   PetscFunctionReturn(0);
1059 }
1060 
1061 /*@C
1062   PetscDSGetJacobian - Get the pointwise Jacobian function for given test and basis field
1063 
1064   Not collective
1065 
1066   Input Parameters:
1067 + prob - The PetscDS
1068 . f    - The test field number
1069 - g    - The field number
1070 
1071   Output Parameters:
1072 + g0 - integrand for the test and basis function term
1073 . g1 - integrand for the test function and basis function gradient term
1074 . g2 - integrand for the test function gradient and basis function term
1075 - g3 - integrand for the test function gradient and basis function gradient term
1076 
1077   Note: We are using a first order FEM model for the weak form:
1078 
1079   \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
1080 
1081 The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
1082 
1083 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1084 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1085 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1086 $    PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])
1087 
1088 + dim - the spatial dimension
1089 . Nf - the number of fields
1090 . uOff - the offset into u[] and u_t[] for each field
1091 . uOff_x - the offset into u_x[] for each field
1092 . u - each field evaluated at the current point
1093 . u_t - the time derivative of each field evaluated at the current point
1094 . u_x - the gradient of each field evaluated at the current point
1095 . aOff - the offset into a[] and a_t[] for each auxiliary field
1096 . aOff_x - the offset into a_x[] for each auxiliary field
1097 . a - each auxiliary field evaluated at the current point
1098 . a_t - the time derivative of each auxiliary field evaluated at the current point
1099 . a_x - the gradient of auxiliary each field evaluated at the current point
1100 . t - current time
1101 . u_tShift - the multiplier a for dF/dU_t
1102 . x - coordinates of the current point
1103 . numConstants - number of constant parameters
1104 . constants - constant parameters
1105 - g0 - output values at the current point
1106 
1107   Level: intermediate
1108 
1109 .seealso: PetscDSSetJacobian()
1110 @*/
1111 PetscErrorCode PetscDSGetJacobian(PetscDS prob, PetscInt f, PetscInt g,
1112                                   void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1113                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1114                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1115                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1116                                   void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1117                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1118                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1119                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1120                                   void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1121                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1122                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1123                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1124                                   void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1125                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1126                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1127                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1128 {
1129   PetscFunctionBegin;
1130   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1131   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);
1132   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);
1133   if (g0) {PetscValidPointer(g0, 4); *g0 = prob->g[(f*prob->Nf + g)*4+0];}
1134   if (g1) {PetscValidPointer(g1, 5); *g1 = prob->g[(f*prob->Nf + g)*4+1];}
1135   if (g2) {PetscValidPointer(g2, 6); *g2 = prob->g[(f*prob->Nf + g)*4+2];}
1136   if (g3) {PetscValidPointer(g3, 7); *g3 = prob->g[(f*prob->Nf + g)*4+3];}
1137   PetscFunctionReturn(0);
1138 }
1139 
1140 /*@C
1141   PetscDSSetJacobian - Set the pointwise Jacobian function for given test and basis fields
1142 
1143   Not collective
1144 
1145   Input Parameters:
1146 + prob - The PetscDS
1147 . f    - The test field number
1148 . g    - The field number
1149 . g0 - integrand for the test and basis function term
1150 . g1 - integrand for the test function and basis function gradient term
1151 . g2 - integrand for the test function gradient and basis function term
1152 - g3 - integrand for the test function gradient and basis function gradient term
1153 
1154   Note: We are using a first order FEM model for the weak form:
1155 
1156   \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
1157 
1158 The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
1159 
1160 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1161 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1162 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1163 $    PetscReal t, const PetscReal x[], PetscScalar g0[])
1164 
1165 + dim - the spatial dimension
1166 . Nf - the number of fields
1167 . uOff - the offset into u[] and u_t[] for each field
1168 . uOff_x - the offset into u_x[] for each field
1169 . u - each field evaluated at the current point
1170 . u_t - the time derivative of each field evaluated at the current point
1171 . u_x - the gradient of each field evaluated at the current point
1172 . aOff - the offset into a[] and a_t[] for each auxiliary field
1173 . aOff_x - the offset into a_x[] for each auxiliary field
1174 . a - each auxiliary field evaluated at the current point
1175 . a_t - the time derivative of each auxiliary field evaluated at the current point
1176 . a_x - the gradient of auxiliary each field evaluated at the current point
1177 . t - current time
1178 . u_tShift - the multiplier a for dF/dU_t
1179 . x - coordinates of the current point
1180 . numConstants - number of constant parameters
1181 . constants - constant parameters
1182 - g0 - output values at the current point
1183 
1184   Level: intermediate
1185 
1186 .seealso: PetscDSGetJacobian()
1187 @*/
1188 PetscErrorCode PetscDSSetJacobian(PetscDS prob, PetscInt f, PetscInt g,
1189                                   void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1190                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1191                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1192                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1193                                   void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1194                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1195                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1196                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1197                                   void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1198                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1199                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1200                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1201                                   void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1202                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1203                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1204                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1205 {
1206   PetscErrorCode ierr;
1207 
1208   PetscFunctionBegin;
1209   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1210   if (g0) PetscValidFunction(g0, 4);
1211   if (g1) PetscValidFunction(g1, 5);
1212   if (g2) PetscValidFunction(g2, 6);
1213   if (g3) PetscValidFunction(g3, 7);
1214   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1215   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
1216   ierr = PetscDSEnlarge_Static(prob, PetscMax(f, g)+1);CHKERRQ(ierr);
1217   prob->g[(f*prob->Nf + g)*4+0] = g0;
1218   prob->g[(f*prob->Nf + g)*4+1] = g1;
1219   prob->g[(f*prob->Nf + g)*4+2] = g2;
1220   prob->g[(f*prob->Nf + g)*4+3] = g3;
1221   PetscFunctionReturn(0);
1222 }
1223 
1224 /*@C
1225   PetscDSHasJacobianPreconditioner - Signals that a Jacobian preconditioner matrix has been set
1226 
1227   Not collective
1228 
1229   Input Parameter:
1230 . prob - The PetscDS
1231 
1232   Output Parameter:
1233 . hasJacPre - flag that pointwise function for Jacobian preconditioner matrix has been set
1234 
1235   Level: intermediate
1236 
1237 .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
1238 @*/
1239 PetscErrorCode PetscDSHasJacobianPreconditioner(PetscDS prob, PetscBool *hasJacPre)
1240 {
1241   PetscInt f, g, h;
1242 
1243   PetscFunctionBegin;
1244   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1245   *hasJacPre = PETSC_FALSE;
1246   for (f = 0; f < prob->Nf; ++f) {
1247     for (g = 0; g < prob->Nf; ++g) {
1248       for (h = 0; h < 4; ++h) {
1249         if (prob->gp[(f*prob->Nf + g)*4+h]) *hasJacPre = PETSC_TRUE;
1250       }
1251     }
1252   }
1253   PetscFunctionReturn(0);
1254 }
1255 
1256 /*@C
1257   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.
1258 
1259   Not collective
1260 
1261   Input Parameters:
1262 + prob - The PetscDS
1263 . f    - The test field number
1264 - g    - The field number
1265 
1266   Output Parameters:
1267 + g0 - integrand for the test and basis function term
1268 . g1 - integrand for the test function and basis function gradient term
1269 . g2 - integrand for the test function gradient and basis function term
1270 - g3 - integrand for the test function gradient and basis function gradient term
1271 
1272   Note: We are using a first order FEM model for the weak form:
1273 
1274   \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
1275 
1276 The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
1277 
1278 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1279 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1280 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1281 $    PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])
1282 
1283 + dim - the spatial dimension
1284 . Nf - the number of fields
1285 . uOff - the offset into u[] and u_t[] for each field
1286 . uOff_x - the offset into u_x[] for each field
1287 . u - each field evaluated at the current point
1288 . u_t - the time derivative of each field evaluated at the current point
1289 . u_x - the gradient of each field evaluated at the current point
1290 . aOff - the offset into a[] and a_t[] for each auxiliary field
1291 . aOff_x - the offset into a_x[] for each auxiliary field
1292 . a - each auxiliary field evaluated at the current point
1293 . a_t - the time derivative of each auxiliary field evaluated at the current point
1294 . a_x - the gradient of auxiliary each field evaluated at the current point
1295 . t - current time
1296 . u_tShift - the multiplier a for dF/dU_t
1297 . x - coordinates of the current point
1298 . numConstants - number of constant parameters
1299 . constants - constant parameters
1300 - g0 - output values at the current point
1301 
1302   Level: intermediate
1303 
1304 .seealso: PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
1305 @*/
1306 PetscErrorCode PetscDSGetJacobianPreconditioner(PetscDS prob, PetscInt f, PetscInt g,
1307                                   void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1308                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1309                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1310                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1311                                   void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1312                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1313                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1314                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1315                                   void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1316                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1317                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1318                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1319                                   void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1320                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1321                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1322                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1323 {
1324   PetscFunctionBegin;
1325   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1326   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);
1327   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);
1328   if (g0) {PetscValidPointer(g0, 4); *g0 = prob->gp[(f*prob->Nf + g)*4+0];}
1329   if (g1) {PetscValidPointer(g1, 5); *g1 = prob->gp[(f*prob->Nf + g)*4+1];}
1330   if (g2) {PetscValidPointer(g2, 6); *g2 = prob->gp[(f*prob->Nf + g)*4+2];}
1331   if (g3) {PetscValidPointer(g3, 7); *g3 = prob->gp[(f*prob->Nf + g)*4+3];}
1332   PetscFunctionReturn(0);
1333 }
1334 
1335 /*@C
1336   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.
1337 
1338   Not collective
1339 
1340   Input Parameters:
1341 + prob - The PetscDS
1342 . f    - The test field number
1343 . g    - The field number
1344 . g0 - integrand for the test and basis function term
1345 . g1 - integrand for the test function and basis function gradient term
1346 . g2 - integrand for the test function gradient and basis function term
1347 - g3 - integrand for the test function gradient and basis function gradient term
1348 
1349   Note: We are using a first order FEM model for the weak form:
1350 
1351   \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
1352 
1353 The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
1354 
1355 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1356 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1357 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1358 $    PetscReal t, const PetscReal x[], PetscScalar g0[])
1359 
1360 + dim - the spatial dimension
1361 . Nf - the number of fields
1362 . uOff - the offset into u[] and u_t[] for each field
1363 . uOff_x - the offset into u_x[] for each field
1364 . u - each field evaluated at the current point
1365 . u_t - the time derivative of each field evaluated at the current point
1366 . u_x - the gradient of each field evaluated at the current point
1367 . aOff - the offset into a[] and a_t[] for each auxiliary field
1368 . aOff_x - the offset into a_x[] for each auxiliary field
1369 . a - each auxiliary field evaluated at the current point
1370 . a_t - the time derivative of each auxiliary field evaluated at the current point
1371 . a_x - the gradient of auxiliary each field evaluated at the current point
1372 . t - current time
1373 . u_tShift - the multiplier a for dF/dU_t
1374 . x - coordinates of the current point
1375 . numConstants - number of constant parameters
1376 . constants - constant parameters
1377 - g0 - output values at the current point
1378 
1379   Level: intermediate
1380 
1381 .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobian()
1382 @*/
1383 PetscErrorCode PetscDSSetJacobianPreconditioner(PetscDS prob, PetscInt f, PetscInt g,
1384                                   void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1385                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1386                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1387                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1388                                   void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1389                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1390                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1391                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1392                                   void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1393                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1394                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1395                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1396                                   void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1397                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1398                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1399                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1400 {
1401   PetscErrorCode ierr;
1402 
1403   PetscFunctionBegin;
1404   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1405   if (g0) PetscValidFunction(g0, 4);
1406   if (g1) PetscValidFunction(g1, 5);
1407   if (g2) PetscValidFunction(g2, 6);
1408   if (g3) PetscValidFunction(g3, 7);
1409   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1410   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
1411   ierr = PetscDSEnlarge_Static(prob, PetscMax(f, g)+1);CHKERRQ(ierr);
1412   prob->gp[(f*prob->Nf + g)*4+0] = g0;
1413   prob->gp[(f*prob->Nf + g)*4+1] = g1;
1414   prob->gp[(f*prob->Nf + g)*4+2] = g2;
1415   prob->gp[(f*prob->Nf + g)*4+3] = g3;
1416   PetscFunctionReturn(0);
1417 }
1418 
1419 /*@C
1420   PetscDSHasDynamicJacobian - Signals that a dynamic Jacobian, dF/du_t, has been set
1421 
1422   Not collective
1423 
1424   Input Parameter:
1425 . prob - The PetscDS
1426 
1427   Output Parameter:
1428 . hasDynJac - flag that pointwise function for dynamic Jacobian has been set
1429 
1430   Level: intermediate
1431 
1432 .seealso: PetscDSGetDynamicJacobian(), PetscDSSetDynamicJacobian(), PetscDSGetJacobian()
1433 @*/
1434 PetscErrorCode PetscDSHasDynamicJacobian(PetscDS prob, PetscBool *hasDynJac)
1435 {
1436   PetscInt f, g, h;
1437 
1438   PetscFunctionBegin;
1439   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1440   *hasDynJac = PETSC_FALSE;
1441   for (f = 0; f < prob->Nf; ++f) {
1442     for (g = 0; g < prob->Nf; ++g) {
1443       for (h = 0; h < 4; ++h) {
1444         if (prob->gt[(f*prob->Nf + g)*4+h]) *hasDynJac = PETSC_TRUE;
1445       }
1446     }
1447   }
1448   PetscFunctionReturn(0);
1449 }
1450 
1451 /*@C
1452   PetscDSGetDynamicJacobian - Get the pointwise dynamic Jacobian, dF/du_t, function for given test and basis field
1453 
1454   Not collective
1455 
1456   Input Parameters:
1457 + prob - The PetscDS
1458 . f    - The test field number
1459 - g    - The field number
1460 
1461   Output Parameters:
1462 + g0 - integrand for the test and basis function term
1463 . g1 - integrand for the test function and basis function gradient term
1464 . g2 - integrand for the test function gradient and basis function term
1465 - g3 - integrand for the test function gradient and basis function gradient term
1466 
1467   Note: We are using a first order FEM model for the weak form:
1468 
1469   \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
1470 
1471 The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
1472 
1473 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1474 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1475 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1476 $    PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])
1477 
1478 + dim - the spatial dimension
1479 . Nf - the number of fields
1480 . uOff - the offset into u[] and u_t[] for each field
1481 . uOff_x - the offset into u_x[] for each field
1482 . u - each field evaluated at the current point
1483 . u_t - the time derivative of each field evaluated at the current point
1484 . u_x - the gradient of each field evaluated at the current point
1485 . aOff - the offset into a[] and a_t[] for each auxiliary field
1486 . aOff_x - the offset into a_x[] for each auxiliary field
1487 . a - each auxiliary field evaluated at the current point
1488 . a_t - the time derivative of each auxiliary field evaluated at the current point
1489 . a_x - the gradient of auxiliary each field evaluated at the current point
1490 . t - current time
1491 . u_tShift - the multiplier a for dF/dU_t
1492 . x - coordinates of the current point
1493 . numConstants - number of constant parameters
1494 . constants - constant parameters
1495 - g0 - output values at the current point
1496 
1497   Level: intermediate
1498 
1499 .seealso: PetscDSSetJacobian()
1500 @*/
1501 PetscErrorCode PetscDSGetDynamicJacobian(PetscDS prob, PetscInt f, PetscInt g,
1502                                          void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1503                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1504                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1505                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1506                                          void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1507                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1508                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1509                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1510                                          void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1511                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1512                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1513                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1514                                          void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1515                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1516                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1517                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1518 {
1519   PetscFunctionBegin;
1520   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1521   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);
1522   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);
1523   if (g0) {PetscValidPointer(g0, 4); *g0 = prob->gt[(f*prob->Nf + g)*4+0];}
1524   if (g1) {PetscValidPointer(g1, 5); *g1 = prob->gt[(f*prob->Nf + g)*4+1];}
1525   if (g2) {PetscValidPointer(g2, 6); *g2 = prob->gt[(f*prob->Nf + g)*4+2];}
1526   if (g3) {PetscValidPointer(g3, 7); *g3 = prob->gt[(f*prob->Nf + g)*4+3];}
1527   PetscFunctionReturn(0);
1528 }
1529 
1530 /*@C
1531   PetscDSSetDynamicJacobian - Set the pointwise dynamic Jacobian, dF/du_t, function for given test and basis fields
1532 
1533   Not collective
1534 
1535   Input Parameters:
1536 + prob - The PetscDS
1537 . f    - The test field number
1538 . g    - The field number
1539 . g0 - integrand for the test and basis function term
1540 . g1 - integrand for the test function and basis function gradient term
1541 . g2 - integrand for the test function gradient and basis function term
1542 - g3 - integrand for the test function gradient and basis function gradient term
1543 
1544   Note: We are using a first order FEM model for the weak form:
1545 
1546   \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
1547 
1548 The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
1549 
1550 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1551 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1552 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1553 $    PetscReal t, const PetscReal x[], PetscScalar g0[])
1554 
1555 + dim - the spatial dimension
1556 . Nf - the number of fields
1557 . uOff - the offset into u[] and u_t[] for each field
1558 . uOff_x - the offset into u_x[] for each field
1559 . u - each field evaluated at the current point
1560 . u_t - the time derivative of each field evaluated at the current point
1561 . u_x - the gradient of each field evaluated at the current point
1562 . aOff - the offset into a[] and a_t[] for each auxiliary field
1563 . aOff_x - the offset into a_x[] for each auxiliary field
1564 . a - each auxiliary field evaluated at the current point
1565 . a_t - the time derivative of each auxiliary field evaluated at the current point
1566 . a_x - the gradient of auxiliary each field evaluated at the current point
1567 . t - current time
1568 . u_tShift - the multiplier a for dF/dU_t
1569 . x - coordinates of the current point
1570 . numConstants - number of constant parameters
1571 . constants - constant parameters
1572 - g0 - output values at the current point
1573 
1574   Level: intermediate
1575 
1576 .seealso: PetscDSGetJacobian()
1577 @*/
1578 PetscErrorCode PetscDSSetDynamicJacobian(PetscDS prob, PetscInt f, PetscInt g,
1579                                          void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1580                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1581                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1582                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1583                                          void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1584                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1585                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1586                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1587                                          void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1588                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1589                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1590                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1591                                          void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1592                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1593                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1594                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1595 {
1596   PetscErrorCode ierr;
1597 
1598   PetscFunctionBegin;
1599   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1600   if (g0) PetscValidFunction(g0, 4);
1601   if (g1) PetscValidFunction(g1, 5);
1602   if (g2) PetscValidFunction(g2, 6);
1603   if (g3) PetscValidFunction(g3, 7);
1604   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1605   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
1606   ierr = PetscDSEnlarge_Static(prob, PetscMax(f, g)+1);CHKERRQ(ierr);
1607   prob->gt[(f*prob->Nf + g)*4+0] = g0;
1608   prob->gt[(f*prob->Nf + g)*4+1] = g1;
1609   prob->gt[(f*prob->Nf + g)*4+2] = g2;
1610   prob->gt[(f*prob->Nf + g)*4+3] = g3;
1611   PetscFunctionReturn(0);
1612 }
1613 
1614 /*@C
1615   PetscDSGetRiemannSolver - Returns the Riemann solver for the given field
1616 
1617   Not collective
1618 
1619   Input Arguments:
1620 + prob - The PetscDS object
1621 - f    - The field number
1622 
1623   Output Argument:
1624 . r    - Riemann solver
1625 
1626   Calling sequence for r:
1627 
1628 $ r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx)
1629 
1630 + dim  - The spatial dimension
1631 . Nf   - The number of fields
1632 . x    - The coordinates at a point on the interface
1633 . n    - The normal vector to the interface
1634 . uL   - The state vector to the left of the interface
1635 . uR   - The state vector to the right of the interface
1636 . flux - output array of flux through the interface
1637 . numConstants - number of constant parameters
1638 . constants - constant parameters
1639 - ctx  - optional user context
1640 
1641   Level: intermediate
1642 
1643 .seealso: PetscDSSetRiemannSolver()
1644 @*/
1645 PetscErrorCode PetscDSGetRiemannSolver(PetscDS prob, PetscInt f,
1646                                        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))
1647 {
1648   PetscFunctionBegin;
1649   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1650   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);
1651   PetscValidPointer(r, 3);
1652   *r = prob->r[f];
1653   PetscFunctionReturn(0);
1654 }
1655 
1656 /*@C
1657   PetscDSSetRiemannSolver - Sets the Riemann solver for the given field
1658 
1659   Not collective
1660 
1661   Input Arguments:
1662 + prob - The PetscDS object
1663 . f    - The field number
1664 - r    - Riemann solver
1665 
1666   Calling sequence for r:
1667 
1668 $ r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx)
1669 
1670 + dim  - The spatial dimension
1671 . Nf   - The number of fields
1672 . x    - The coordinates at a point on the interface
1673 . n    - The normal vector to the interface
1674 . uL   - The state vector to the left of the interface
1675 . uR   - The state vector to the right of the interface
1676 . flux - output array of flux through the interface
1677 . numConstants - number of constant parameters
1678 . constants - constant parameters
1679 - ctx  - optional user context
1680 
1681   Level: intermediate
1682 
1683 .seealso: PetscDSGetRiemannSolver()
1684 @*/
1685 PetscErrorCode PetscDSSetRiemannSolver(PetscDS prob, PetscInt f,
1686                                        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))
1687 {
1688   PetscErrorCode ierr;
1689 
1690   PetscFunctionBegin;
1691   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1692   if (r) PetscValidFunction(r, 3);
1693   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1694   ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr);
1695   prob->r[f] = r;
1696   PetscFunctionReturn(0);
1697 }
1698 
1699 /*@C
1700   PetscDSGetUpdate - Get the pointwise update function for a given field
1701 
1702   Not collective
1703 
1704   Input Parameters:
1705 + prob - The PetscDS
1706 - f    - The field number
1707 
1708   Output Parameters:
1709 + update - update function
1710 
1711   Note: The calling sequence for the callback update is given by:
1712 
1713 $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1714 $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1715 $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1716 $        PetscReal t, const PetscReal x[], PetscScalar uNew[])
1717 
1718 + dim - the spatial dimension
1719 . Nf - the number of fields
1720 . uOff - the offset into u[] and u_t[] for each field
1721 . uOff_x - the offset into u_x[] for each field
1722 . u - each field evaluated at the current point
1723 . u_t - the time derivative of each field evaluated at the current point
1724 . u_x - the gradient of each field evaluated at the current point
1725 . aOff - the offset into a[] and a_t[] for each auxiliary field
1726 . aOff_x - the offset into a_x[] for each auxiliary field
1727 . a - each auxiliary field evaluated at the current point
1728 . a_t - the time derivative of each auxiliary field evaluated at the current point
1729 . a_x - the gradient of auxiliary each field evaluated at the current point
1730 . t - current time
1731 . x - coordinates of the current point
1732 - uNew - new value for field at the current point
1733 
1734   Level: intermediate
1735 
1736 .seealso: PetscDSSetUpdate(), PetscDSSetResidual()
1737 @*/
1738 PetscErrorCode PetscDSGetUpdate(PetscDS prob, PetscInt f,
1739                                   void (**update)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1740                                                   const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1741                                                   const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1742                                                   PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[]))
1743 {
1744   PetscFunctionBegin;
1745   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1746   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);
1747   if (update) {PetscValidPointer(update, 3); *update = prob->update[f];}
1748   PetscFunctionReturn(0);
1749 }
1750 
1751 /*@C
1752   PetscDSSetUpdate - Set the pointwise update function for a given field
1753 
1754   Not collective
1755 
1756   Input Parameters:
1757 + prob   - The PetscDS
1758 . f      - The field number
1759 - update - update function
1760 
1761   Note: The calling sequence for the callback update is given by:
1762 
1763 $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1764 $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1765 $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1766 $        PetscReal t, const PetscReal x[], PetscScalar uNew[])
1767 
1768 + dim - the spatial dimension
1769 . Nf - the number of fields
1770 . uOff - the offset into u[] and u_t[] for each field
1771 . uOff_x - the offset into u_x[] for each field
1772 . u - each field evaluated at the current point
1773 . u_t - the time derivative of each field evaluated at the current point
1774 . u_x - the gradient of each field evaluated at the current point
1775 . aOff - the offset into a[] and a_t[] for each auxiliary field
1776 . aOff_x - the offset into a_x[] for each auxiliary field
1777 . a - each auxiliary field evaluated at the current point
1778 . a_t - the time derivative of each auxiliary field evaluated at the current point
1779 . a_x - the gradient of auxiliary each field evaluated at the current point
1780 . t - current time
1781 . x - coordinates of the current point
1782 - uNew - new field values at the current point
1783 
1784   Level: intermediate
1785 
1786 .seealso: PetscDSGetResidual()
1787 @*/
1788 PetscErrorCode PetscDSSetUpdate(PetscDS prob, PetscInt f,
1789                                 void (*update)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1790                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1791                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1792                                                PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[]))
1793 {
1794   PetscErrorCode ierr;
1795 
1796   PetscFunctionBegin;
1797   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1798   if (update) PetscValidFunction(update, 3);
1799   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1800   ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr);
1801   prob->update[f] = update;
1802   PetscFunctionReturn(0);
1803 }
1804 
1805 PetscErrorCode PetscDSGetContext(PetscDS prob, PetscInt f, void **ctx)
1806 {
1807   PetscFunctionBegin;
1808   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1809   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);
1810   PetscValidPointer(ctx, 3);
1811   *ctx = prob->ctx[f];
1812   PetscFunctionReturn(0);
1813 }
1814 
1815 PetscErrorCode PetscDSSetContext(PetscDS prob, PetscInt f, void *ctx)
1816 {
1817   PetscErrorCode ierr;
1818 
1819   PetscFunctionBegin;
1820   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1821   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1822   ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr);
1823   prob->ctx[f] = ctx;
1824   PetscFunctionReturn(0);
1825 }
1826 
1827 /*@C
1828   PetscDSGetBdResidual - Get the pointwise boundary residual function for a given test field
1829 
1830   Not collective
1831 
1832   Input Parameters:
1833 + prob - The PetscDS
1834 - f    - The test field number
1835 
1836   Output Parameters:
1837 + f0 - boundary integrand for the test function term
1838 - f1 - boundary integrand for the test function gradient term
1839 
1840   Note: We are using a first order FEM model for the weak form:
1841 
1842   \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
1843 
1844 The calling sequence for the callbacks f0 and f1 is given by:
1845 
1846 $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1847 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1848 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1849 $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])
1850 
1851 + dim - the spatial dimension
1852 . Nf - the number of fields
1853 . uOff - the offset into u[] and u_t[] for each field
1854 . uOff_x - the offset into u_x[] for each field
1855 . u - each field evaluated at the current point
1856 . u_t - the time derivative of each field evaluated at the current point
1857 . u_x - the gradient of each field evaluated at the current point
1858 . aOff - the offset into a[] and a_t[] for each auxiliary field
1859 . aOff_x - the offset into a_x[] for each auxiliary field
1860 . a - each auxiliary field evaluated at the current point
1861 . a_t - the time derivative of each auxiliary field evaluated at the current point
1862 . a_x - the gradient of auxiliary each field evaluated at the current point
1863 . t - current time
1864 . x - coordinates of the current point
1865 . n - unit normal at the current point
1866 . numConstants - number of constant parameters
1867 . constants - constant parameters
1868 - f0 - output values at the current point
1869 
1870   Level: intermediate
1871 
1872 .seealso: PetscDSSetBdResidual()
1873 @*/
1874 PetscErrorCode PetscDSGetBdResidual(PetscDS prob, PetscInt f,
1875                                     void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1876                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1877                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1878                                                 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
1879                                     void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1880                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1881                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1882                                                 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
1883 {
1884   PetscFunctionBegin;
1885   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1886   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);
1887   if (f0) {PetscValidPointer(f0, 3); *f0 = prob->fBd[f*2+0];}
1888   if (f1) {PetscValidPointer(f1, 4); *f1 = prob->fBd[f*2+1];}
1889   PetscFunctionReturn(0);
1890 }
1891 
1892 /*@C
1893   PetscDSSetBdResidual - Get the pointwise boundary residual function for a given test field
1894 
1895   Not collective
1896 
1897   Input Parameters:
1898 + prob - The PetscDS
1899 . f    - The test field number
1900 . f0 - boundary integrand for the test function term
1901 - f1 - boundary integrand for the test function gradient term
1902 
1903   Note: We are using a first order FEM model for the weak form:
1904 
1905   \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
1906 
1907 The calling sequence for the callbacks f0 and f1 is given by:
1908 
1909 $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1910 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1911 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1912 $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])
1913 
1914 + dim - the spatial dimension
1915 . Nf - the number of fields
1916 . uOff - the offset into u[] and u_t[] for each field
1917 . uOff_x - the offset into u_x[] for each field
1918 . u - each field evaluated at the current point
1919 . u_t - the time derivative of each field evaluated at the current point
1920 . u_x - the gradient of each field evaluated at the current point
1921 . aOff - the offset into a[] and a_t[] for each auxiliary field
1922 . aOff_x - the offset into a_x[] for each auxiliary field
1923 . a - each auxiliary field evaluated at the current point
1924 . a_t - the time derivative of each auxiliary field evaluated at the current point
1925 . a_x - the gradient of auxiliary each field evaluated at the current point
1926 . t - current time
1927 . x - coordinates of the current point
1928 . n - unit normal at the current point
1929 . numConstants - number of constant parameters
1930 . constants - constant parameters
1931 - f0 - output values at the current point
1932 
1933   Level: intermediate
1934 
1935 .seealso: PetscDSGetBdResidual()
1936 @*/
1937 PetscErrorCode PetscDSSetBdResidual(PetscDS prob, PetscInt f,
1938                                     void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1939                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1940                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1941                                                PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
1942                                     void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1943                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1944                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1945                                                PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
1946 {
1947   PetscErrorCode ierr;
1948 
1949   PetscFunctionBegin;
1950   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1951   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1952   ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr);
1953   if (f0) {PetscValidFunction(f0, 3); prob->fBd[f*2+0] = f0;}
1954   if (f1) {PetscValidFunction(f1, 4); prob->fBd[f*2+1] = f1;}
1955   PetscFunctionReturn(0);
1956 }
1957 
1958 /*@C
1959   PetscDSGetBdJacobian - Get the pointwise boundary Jacobian function for given test and basis field
1960 
1961   Not collective
1962 
1963   Input Parameters:
1964 + prob - The PetscDS
1965 . f    - The test field number
1966 - g    - The field number
1967 
1968   Output Parameters:
1969 + g0 - integrand for the test and basis function term
1970 . g1 - integrand for the test function and basis function gradient term
1971 . g2 - integrand for the test function gradient and basis function term
1972 - g3 - integrand for the test function gradient and basis function gradient term
1973 
1974   Note: We are using a first order FEM model for the weak form:
1975 
1976   \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
1977 
1978 The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
1979 
1980 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1981 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1982 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1983 $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[])
1984 
1985 + dim - the spatial dimension
1986 . Nf - the number of fields
1987 . uOff - the offset into u[] and u_t[] for each field
1988 . uOff_x - the offset into u_x[] for each field
1989 . u - each field evaluated at the current point
1990 . u_t - the time derivative of each field evaluated at the current point
1991 . u_x - the gradient of each field evaluated at the current point
1992 . aOff - the offset into a[] and a_t[] for each auxiliary field
1993 . aOff_x - the offset into a_x[] for each auxiliary field
1994 . a - each auxiliary field evaluated at the current point
1995 . a_t - the time derivative of each auxiliary field evaluated at the current point
1996 . a_x - the gradient of auxiliary each field evaluated at the current point
1997 . t - current time
1998 . u_tShift - the multiplier a for dF/dU_t
1999 . x - coordinates of the current point
2000 . n - normal at the current point
2001 . numConstants - number of constant parameters
2002 . constants - constant parameters
2003 - g0 - output values at the current point
2004 
2005   Level: intermediate
2006 
2007 .seealso: PetscDSSetBdJacobian()
2008 @*/
2009 PetscErrorCode PetscDSGetBdJacobian(PetscDS prob, PetscInt f, PetscInt g,
2010                                     void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2011                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2012                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2013                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
2014                                     void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2015                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2016                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2017                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
2018                                     void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2019                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2020                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2021                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
2022                                     void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2023                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2024                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2025                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2026 {
2027   PetscFunctionBegin;
2028   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2029   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);
2030   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);
2031   if (g0) {PetscValidPointer(g0, 4); *g0 = prob->gBd[(f*prob->Nf + g)*4+0];}
2032   if (g1) {PetscValidPointer(g1, 5); *g1 = prob->gBd[(f*prob->Nf + g)*4+1];}
2033   if (g2) {PetscValidPointer(g2, 6); *g2 = prob->gBd[(f*prob->Nf + g)*4+2];}
2034   if (g3) {PetscValidPointer(g3, 7); *g3 = prob->gBd[(f*prob->Nf + g)*4+3];}
2035   PetscFunctionReturn(0);
2036 }
2037 
2038 /*@C
2039   PetscDSSetBdJacobian - Set the pointwise boundary Jacobian function for given test and basis field
2040 
2041   Not collective
2042 
2043   Input Parameters:
2044 + prob - The PetscDS
2045 . f    - The test field number
2046 . g    - The field number
2047 . g0 - integrand for the test and basis function term
2048 . g1 - integrand for the test function and basis function gradient term
2049 . g2 - integrand for the test function gradient and basis function term
2050 - g3 - integrand for the test function gradient and basis function gradient term
2051 
2052   Note: We are using a first order FEM model for the weak form:
2053 
2054   \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
2055 
2056 The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
2057 
2058 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2059 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2060 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2061 $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[])
2062 
2063 + dim - the spatial dimension
2064 . Nf - the number of fields
2065 . uOff - the offset into u[] and u_t[] for each field
2066 . uOff_x - the offset into u_x[] for each field
2067 . u - each field evaluated at the current point
2068 . u_t - the time derivative of each field evaluated at the current point
2069 . u_x - the gradient of each field evaluated at the current point
2070 . aOff - the offset into a[] and a_t[] for each auxiliary field
2071 . aOff_x - the offset into a_x[] for each auxiliary field
2072 . a - each auxiliary field evaluated at the current point
2073 . a_t - the time derivative of each auxiliary field evaluated at the current point
2074 . a_x - the gradient of auxiliary each field evaluated at the current point
2075 . t - current time
2076 . u_tShift - the multiplier a for dF/dU_t
2077 . x - coordinates of the current point
2078 . n - normal at the current point
2079 . numConstants - number of constant parameters
2080 . constants - constant parameters
2081 - g0 - output values at the current point
2082 
2083   Level: intermediate
2084 
2085 .seealso: PetscDSGetBdJacobian()
2086 @*/
2087 PetscErrorCode PetscDSSetBdJacobian(PetscDS prob, PetscInt f, PetscInt g,
2088                                     void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2089                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2090                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2091                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
2092                                     void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2093                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2094                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2095                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
2096                                     void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2097                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2098                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2099                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
2100                                     void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2101                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2102                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2103                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2104 {
2105   PetscErrorCode ierr;
2106 
2107   PetscFunctionBegin;
2108   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2109   if (g0) PetscValidFunction(g0, 4);
2110   if (g1) PetscValidFunction(g1, 5);
2111   if (g2) PetscValidFunction(g2, 6);
2112   if (g3) PetscValidFunction(g3, 7);
2113   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
2114   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
2115   ierr = PetscDSEnlarge_Static(prob, PetscMax(f, g)+1);CHKERRQ(ierr);
2116   prob->gBd[(f*prob->Nf + g)*4+0] = g0;
2117   prob->gBd[(f*prob->Nf + g)*4+1] = g1;
2118   prob->gBd[(f*prob->Nf + g)*4+2] = g2;
2119   prob->gBd[(f*prob->Nf + g)*4+3] = g3;
2120   PetscFunctionReturn(0);
2121 }
2122 
2123 /*@C
2124   PetscDSGetExactSolution - Get the pointwise exact solution function for a given test field
2125 
2126   Not collective
2127 
2128   Input Parameters:
2129 + prob - The PetscDS
2130 - f    - The test field number
2131 
2132   Output Parameter:
2133 . exactSol - exact solution for the test field
2134 
2135   Note: The calling sequence for the solution functions is given by:
2136 
2137 $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2138 
2139 + dim - the spatial dimension
2140 . t - current time
2141 . x - coordinates of the current point
2142 . Nc - the number of field components
2143 . u - the solution field evaluated at the current point
2144 - ctx - a user context
2145 
2146   Level: intermediate
2147 
2148 .seealso: PetscDSSetExactSolution()
2149 @*/
2150 PetscErrorCode PetscDSGetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx))
2151 {
2152   PetscFunctionBegin;
2153   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2154   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);
2155   if (sol) {PetscValidPointer(sol, 3); *sol = prob->exactSol[f];}
2156   PetscFunctionReturn(0);
2157 }
2158 
2159 /*@C
2160   PetscDSSetExactSolution - Get the pointwise exact solution function for a given test field
2161 
2162   Not collective
2163 
2164   Input Parameters:
2165 + prob - The PetscDS
2166 . f    - The test field number
2167 - sol  - solution function for the test fields
2168 
2169   Note: The calling sequence for solution functions is given by:
2170 
2171 $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2172 
2173 + dim - the spatial dimension
2174 . t - current time
2175 . x - coordinates of the current point
2176 . Nc - the number of field components
2177 . u - the solution field evaluated at the current point
2178 - ctx - a user context
2179 
2180   Level: intermediate
2181 
2182 .seealso: PetscDSGetExactSolution()
2183 @*/
2184 PetscErrorCode PetscDSSetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx))
2185 {
2186   PetscErrorCode ierr;
2187 
2188   PetscFunctionBegin;
2189   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2190   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
2191   ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr);
2192   if (sol) {PetscValidFunction(sol, 3); prob->exactSol[f] = sol;}
2193   PetscFunctionReturn(0);
2194 }
2195 
2196 /*@C
2197   PetscDSGetConstants - Returns the array of constants passed to point functions
2198 
2199   Not collective
2200 
2201   Input Parameter:
2202 . prob - The PetscDS object
2203 
2204   Output Parameters:
2205 + numConstants - The number of constants
2206 - constants    - The array of constants, NULL if there are none
2207 
2208   Level: intermediate
2209 
2210 .seealso: PetscDSSetConstants(), PetscDSCreate()
2211 @*/
2212 PetscErrorCode PetscDSGetConstants(PetscDS prob, PetscInt *numConstants, const PetscScalar *constants[])
2213 {
2214   PetscFunctionBegin;
2215   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2216   if (numConstants) {PetscValidPointer(numConstants, 2); *numConstants = prob->numConstants;}
2217   if (constants)    {PetscValidPointer(constants, 3);    *constants    = prob->constants;}
2218   PetscFunctionReturn(0);
2219 }
2220 
2221 /*@C
2222   PetscDSSetConstants - Set the array of constants passed to point functions
2223 
2224   Not collective
2225 
2226   Input Parameters:
2227 + prob         - The PetscDS object
2228 . numConstants - The number of constants
2229 - constants    - The array of constants, NULL if there are none
2230 
2231   Level: intermediate
2232 
2233 .seealso: PetscDSGetConstants(), PetscDSCreate()
2234 @*/
2235 PetscErrorCode PetscDSSetConstants(PetscDS prob, PetscInt numConstants, PetscScalar constants[])
2236 {
2237   PetscErrorCode ierr;
2238 
2239   PetscFunctionBegin;
2240   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2241   if (numConstants != prob->numConstants) {
2242     ierr = PetscFree(prob->constants);CHKERRQ(ierr);
2243     prob->numConstants = numConstants;
2244     if (prob->numConstants) {
2245       ierr = PetscMalloc1(prob->numConstants, &prob->constants);CHKERRQ(ierr);
2246     } else {
2247       prob->constants = NULL;
2248     }
2249   }
2250   if (prob->numConstants) {
2251     PetscValidPointer(constants, 3);
2252     ierr = PetscMemcpy(prob->constants, constants, prob->numConstants * sizeof(PetscScalar));CHKERRQ(ierr);
2253   }
2254   PetscFunctionReturn(0);
2255 }
2256 
2257 /*@
2258   PetscDSGetFieldIndex - Returns the index of the given field
2259 
2260   Not collective
2261 
2262   Input Parameters:
2263 + prob - The PetscDS object
2264 - disc - The discretization object
2265 
2266   Output Parameter:
2267 . f - The field number
2268 
2269   Level: beginner
2270 
2271 .seealso: PetscGetDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
2272 @*/
2273 PetscErrorCode PetscDSGetFieldIndex(PetscDS prob, PetscObject disc, PetscInt *f)
2274 {
2275   PetscInt g;
2276 
2277   PetscFunctionBegin;
2278   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2279   PetscValidPointer(f, 3);
2280   *f = -1;
2281   for (g = 0; g < prob->Nf; ++g) {if (disc == prob->disc[g]) break;}
2282   if (g == prob->Nf) SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Field not found in PetscDS.");
2283   *f = g;
2284   PetscFunctionReturn(0);
2285 }
2286 
2287 /*@
2288   PetscDSGetFieldSize - Returns the size of the given field in the full space basis
2289 
2290   Not collective
2291 
2292   Input Parameters:
2293 + prob - The PetscDS object
2294 - f - The field number
2295 
2296   Output Parameter:
2297 . size - The size
2298 
2299   Level: beginner
2300 
2301 .seealso: PetscDSGetFieldOffset(), PetscDSGetNumFields(), PetscDSCreate()
2302 @*/
2303 PetscErrorCode PetscDSGetFieldSize(PetscDS prob, PetscInt f, PetscInt *size)
2304 {
2305   PetscErrorCode ierr;
2306 
2307   PetscFunctionBegin;
2308   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2309   PetscValidPointer(size, 3);
2310   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);
2311   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
2312   *size = prob->Nb[f];
2313   PetscFunctionReturn(0);
2314 }
2315 
2316 /*@
2317   PetscDSGetFieldOffset - Returns the offset of the given field in the full space basis
2318 
2319   Not collective
2320 
2321   Input Parameters:
2322 + prob - The PetscDS object
2323 - f - The field number
2324 
2325   Output Parameter:
2326 . off - The offset
2327 
2328   Level: beginner
2329 
2330 .seealso: PetscDSGetFieldSize(), PetscDSGetNumFields(), PetscDSCreate()
2331 @*/
2332 PetscErrorCode PetscDSGetFieldOffset(PetscDS prob, PetscInt f, PetscInt *off)
2333 {
2334   PetscInt       size, g;
2335   PetscErrorCode ierr;
2336 
2337   PetscFunctionBegin;
2338   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2339   PetscValidPointer(off, 3);
2340   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);
2341   *off = 0;
2342   for (g = 0; g < f; ++g) {
2343     ierr = PetscDSGetFieldSize(prob, g, &size);CHKERRQ(ierr);
2344     *off += size;
2345   }
2346   PetscFunctionReturn(0);
2347 }
2348 
2349 /*@
2350   PetscDSGetDimensions - Returns the size of the approximation space for each field on an evaluation point
2351 
2352   Not collective
2353 
2354   Input Parameter:
2355 . prob - The PetscDS object
2356 
2357   Output Parameter:
2358 . dimensions - The number of dimensions
2359 
2360   Level: beginner
2361 
2362 .seealso: PetscDSGetComponentOffsets(), PetscDSGetNumFields(), PetscDSCreate()
2363 @*/
2364 PetscErrorCode PetscDSGetDimensions(PetscDS prob, PetscInt *dimensions[])
2365 {
2366   PetscErrorCode ierr;
2367 
2368   PetscFunctionBegin;
2369   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2370   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
2371   PetscValidPointer(dimensions, 2);
2372   *dimensions = prob->Nb;
2373   PetscFunctionReturn(0);
2374 }
2375 
2376 /*@
2377   PetscDSGetComponents - Returns the number of components for each field on an evaluation point
2378 
2379   Not collective
2380 
2381   Input Parameter:
2382 . prob - The PetscDS object
2383 
2384   Output Parameter:
2385 . components - The number of components
2386 
2387   Level: beginner
2388 
2389 .seealso: PetscDSGetComponentOffsets(), PetscDSGetNumFields(), PetscDSCreate()
2390 @*/
2391 PetscErrorCode PetscDSGetComponents(PetscDS prob, PetscInt *components[])
2392 {
2393   PetscErrorCode ierr;
2394 
2395   PetscFunctionBegin;
2396   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2397   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
2398   PetscValidPointer(components, 2);
2399   *components = prob->Nc;
2400   PetscFunctionReturn(0);
2401 }
2402 
2403 /*@
2404   PetscDSGetComponentOffset - Returns the offset of the given field on an evaluation point
2405 
2406   Not collective
2407 
2408   Input Parameters:
2409 + prob - The PetscDS object
2410 - f - The field number
2411 
2412   Output Parameter:
2413 . off - The offset
2414 
2415   Level: beginner
2416 
2417 .seealso: PetscDSGetNumFields(), PetscDSCreate()
2418 @*/
2419 PetscErrorCode PetscDSGetComponentOffset(PetscDS prob, PetscInt f, PetscInt *off)
2420 {
2421   PetscFunctionBegin;
2422   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2423   PetscValidPointer(off, 3);
2424   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);
2425   *off = prob->off[f];
2426   PetscFunctionReturn(0);
2427 }
2428 
2429 /*@
2430   PetscDSGetComponentOffsets - Returns the offset of each field on an evaluation point
2431 
2432   Not collective
2433 
2434   Input Parameter:
2435 . prob - The PetscDS object
2436 
2437   Output Parameter:
2438 . offsets - The offsets
2439 
2440   Level: beginner
2441 
2442 .seealso: PetscDSGetNumFields(), PetscDSCreate()
2443 @*/
2444 PetscErrorCode PetscDSGetComponentOffsets(PetscDS prob, PetscInt *offsets[])
2445 {
2446   PetscFunctionBegin;
2447   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2448   PetscValidPointer(offsets, 2);
2449   *offsets = prob->off;
2450   PetscFunctionReturn(0);
2451 }
2452 
2453 /*@
2454   PetscDSGetComponentDerivativeOffsets - Returns the offset of each field derivative on an evaluation point
2455 
2456   Not collective
2457 
2458   Input Parameter:
2459 . prob - The PetscDS object
2460 
2461   Output Parameter:
2462 . offsets - The offsets
2463 
2464   Level: beginner
2465 
2466 .seealso: PetscDSGetNumFields(), PetscDSCreate()
2467 @*/
2468 PetscErrorCode PetscDSGetComponentDerivativeOffsets(PetscDS prob, PetscInt *offsets[])
2469 {
2470   PetscFunctionBegin;
2471   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2472   PetscValidPointer(offsets, 2);
2473   *offsets = prob->offDer;
2474   PetscFunctionReturn(0);
2475 }
2476 
2477 /*@C
2478   PetscDSGetTabulation - Return the basis tabulation at quadrature points for the volume discretization
2479 
2480   Not collective
2481 
2482   Input Parameter:
2483 . prob - The PetscDS object
2484 
2485   Output Parameters:
2486 + basis - The basis function tabulation at quadrature points
2487 - basisDer - The basis function derivative tabulation at quadrature points
2488 
2489   Level: intermediate
2490 
2491 .seealso: PetscDSCreate()
2492 @*/
2493 PetscErrorCode PetscDSGetTabulation(PetscDS prob, PetscReal ***basis, PetscReal ***basisDer)
2494 {
2495   PetscErrorCode ierr;
2496 
2497   PetscFunctionBegin;
2498   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2499   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
2500   if (basis)    {PetscValidPointer(basis, 2);    *basis    = prob->basis;}
2501   if (basisDer) {PetscValidPointer(basisDer, 3); *basisDer = prob->basisDer;}
2502   PetscFunctionReturn(0);
2503 }
2504 
2505 /*@C
2506   PetscDSGetFaceTabulation - Return the basis tabulation at quadrature points on the faces
2507 
2508   Not collective
2509 
2510   Input Parameter:
2511 . prob - The PetscDS object
2512 
2513   Output Parameters:
2514 + basisFace - The basis function tabulation at quadrature points
2515 - basisDerFace - The basis function derivative tabulation at quadrature points
2516 
2517   Level: intermediate
2518 
2519 .seealso: PetscDSGetTabulation(), PetscDSCreate()
2520 @*/
2521 PetscErrorCode PetscDSGetFaceTabulation(PetscDS prob, PetscReal ***basis, PetscReal ***basisDer)
2522 {
2523   PetscErrorCode ierr;
2524 
2525   PetscFunctionBegin;
2526   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2527   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
2528   if (basis)    {PetscValidPointer(basis, 2);    *basis    = prob->basisFace;}
2529   if (basisDer) {PetscValidPointer(basisDer, 3); *basisDer = prob->basisDerFace;}
2530   PetscFunctionReturn(0);
2531 }
2532 
2533 PetscErrorCode PetscDSGetEvaluationArrays(PetscDS prob, PetscScalar **u, PetscScalar **u_t, PetscScalar **u_x)
2534 {
2535   PetscErrorCode ierr;
2536 
2537   PetscFunctionBegin;
2538   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2539   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
2540   if (u)   {PetscValidPointer(u, 2);   *u   = prob->u;}
2541   if (u_t) {PetscValidPointer(u_t, 3); *u_t = prob->u_t;}
2542   if (u_x) {PetscValidPointer(u_x, 4); *u_x = prob->u_x;}
2543   PetscFunctionReturn(0);
2544 }
2545 
2546 PetscErrorCode PetscDSGetWeakFormArrays(PetscDS prob, PetscScalar **f0, PetscScalar **f1, PetscScalar **g0, PetscScalar **g1, PetscScalar **g2, PetscScalar **g3)
2547 {
2548   PetscErrorCode ierr;
2549 
2550   PetscFunctionBegin;
2551   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2552   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
2553   if (f0) {PetscValidPointer(f0, 2); *f0 = prob->f0;}
2554   if (f1) {PetscValidPointer(f1, 3); *f1 = prob->f1;}
2555   if (g0) {PetscValidPointer(g0, 4); *g0 = prob->g0;}
2556   if (g1) {PetscValidPointer(g1, 5); *g1 = prob->g1;}
2557   if (g2) {PetscValidPointer(g2, 6); *g2 = prob->g2;}
2558   if (g3) {PetscValidPointer(g3, 7); *g3 = prob->g3;}
2559   PetscFunctionReturn(0);
2560 }
2561 
2562 PetscErrorCode PetscDSGetRefCoordArrays(PetscDS prob, PetscReal **x, PetscScalar **refSpaceDer)
2563 {
2564   PetscErrorCode ierr;
2565 
2566   PetscFunctionBegin;
2567   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2568   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
2569   if (x)           {PetscValidPointer(x, 2);           *x           = prob->x;}
2570   if (refSpaceDer) {PetscValidPointer(refSpaceDer, 3); *refSpaceDer = prob->refSpaceDer;}
2571   PetscFunctionReturn(0);
2572 }
2573 
2574 /*@C
2575   PetscDSAddBoundary - Add a boundary condition to the model
2576 
2577   Input Parameters:
2578 + ds          - The PetscDS object
2579 . type        - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
2580 . name        - The BC name
2581 . labelname   - The label defining constrained points
2582 . field       - The field to constrain
2583 . numcomps    - The number of constrained field components
2584 . comps       - An array of constrained component numbers
2585 . bcFunc      - A pointwise function giving boundary values
2586 . numids      - The number of DMLabel ids for constrained points
2587 . ids         - An array of ids for constrained points
2588 - ctx         - An optional user context for bcFunc
2589 
2590   Options Database Keys:
2591 + -bc_<boundary name> <num> - Overrides the boundary ids
2592 - -bc_<boundary name>_comp <num> - Overrides the boundary components
2593 
2594   Level: developer
2595 
2596 .seealso: PetscDSGetBoundary()
2597 @*/
2598 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)
2599 {
2600   DSBoundary     b;
2601   PetscErrorCode ierr;
2602 
2603   PetscFunctionBegin;
2604   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
2605   ierr = PetscNew(&b);CHKERRQ(ierr);
2606   ierr = PetscStrallocpy(name, (char **) &b->name);CHKERRQ(ierr);
2607   ierr = PetscStrallocpy(labelname, (char **) &b->labelname);CHKERRQ(ierr);
2608   ierr = PetscMalloc1(numcomps, &b->comps);CHKERRQ(ierr);
2609   if (numcomps) {ierr = PetscMemcpy(b->comps, comps, numcomps*sizeof(PetscInt));CHKERRQ(ierr);}
2610   ierr = PetscMalloc1(numids, &b->ids);CHKERRQ(ierr);
2611   if (numids) {ierr = PetscMemcpy(b->ids, ids, numids*sizeof(PetscInt));CHKERRQ(ierr);}
2612   b->type            = type;
2613   b->field           = field;
2614   b->numcomps        = numcomps;
2615   b->func            = bcFunc;
2616   b->numids          = numids;
2617   b->ctx             = ctx;
2618   b->next            = ds->boundary;
2619   ds->boundary       = b;
2620   PetscFunctionReturn(0);
2621 }
2622 
2623 /*@
2624   PetscDSGetNumBoundary - Get the number of registered BC
2625 
2626   Input Parameters:
2627 . ds - The PetscDS object
2628 
2629   Output Parameters:
2630 . numBd - The number of BC
2631 
2632   Level: intermediate
2633 
2634 .seealso: PetscDSAddBoundary(), PetscDSGetBoundary()
2635 @*/
2636 PetscErrorCode PetscDSGetNumBoundary(PetscDS ds, PetscInt *numBd)
2637 {
2638   DSBoundary b = ds->boundary;
2639 
2640   PetscFunctionBegin;
2641   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
2642   PetscValidPointer(numBd, 2);
2643   *numBd = 0;
2644   while (b) {++(*numBd); b = b->next;}
2645   PetscFunctionReturn(0);
2646 }
2647 
2648 /*@C
2649   PetscDSGetBoundary - Add a boundary condition to the model
2650 
2651   Input Parameters:
2652 + ds          - The PetscDS object
2653 - bd          - The BC number
2654 
2655   Output Parameters:
2656 + type        - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
2657 . name        - The BC name
2658 . labelname   - The label defining constrained points
2659 . field       - The field to constrain
2660 . numcomps    - The number of constrained field components
2661 . comps       - An array of constrained component numbers
2662 . bcFunc      - A pointwise function giving boundary values
2663 . numids      - The number of DMLabel ids for constrained points
2664 . ids         - An array of ids for constrained points
2665 - ctx         - An optional user context for bcFunc
2666 
2667   Options Database Keys:
2668 + -bc_<boundary name> <num> - Overrides the boundary ids
2669 - -bc_<boundary name>_comp <num> - Overrides the boundary components
2670 
2671   Level: developer
2672 
2673 .seealso: PetscDSAddBoundary()
2674 @*/
2675 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)
2676 {
2677   DSBoundary b    = ds->boundary;
2678   PetscInt   n    = 0;
2679 
2680   PetscFunctionBegin;
2681   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
2682   while (b) {
2683     if (n == bd) break;
2684     b = b->next;
2685     ++n;
2686   }
2687   if (!b) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n);
2688   if (type) {
2689     PetscValidPointer(type, 3);
2690     *type = b->type;
2691   }
2692   if (name) {
2693     PetscValidPointer(name, 4);
2694     *name = b->name;
2695   }
2696   if (labelname) {
2697     PetscValidPointer(labelname, 5);
2698     *labelname = b->labelname;
2699   }
2700   if (field) {
2701     PetscValidPointer(field, 6);
2702     *field = b->field;
2703   }
2704   if (numcomps) {
2705     PetscValidPointer(numcomps, 7);
2706     *numcomps = b->numcomps;
2707   }
2708   if (comps) {
2709     PetscValidPointer(comps, 8);
2710     *comps = b->comps;
2711   }
2712   if (func) {
2713     PetscValidPointer(func, 9);
2714     *func = b->func;
2715   }
2716   if (numids) {
2717     PetscValidPointer(numids, 10);
2718     *numids = b->numids;
2719   }
2720   if (ids) {
2721     PetscValidPointer(ids, 11);
2722     *ids = b->ids;
2723   }
2724   if (ctx) {
2725     PetscValidPointer(ctx, 12);
2726     *ctx = b->ctx;
2727   }
2728   PetscFunctionReturn(0);
2729 }
2730 
2731 PetscErrorCode PetscDSCopyBoundary(PetscDS probA, PetscDS probB)
2732 {
2733   DSBoundary     b, next, *lastnext;
2734   PetscErrorCode ierr;
2735 
2736   PetscFunctionBegin;
2737   PetscValidHeaderSpecific(probA, PETSCDS_CLASSID, 1);
2738   PetscValidHeaderSpecific(probB, PETSCDS_CLASSID, 2);
2739   if (probA == probB) PetscFunctionReturn(0);
2740   next = probB->boundary;
2741   while (next) {
2742     DSBoundary b = next;
2743 
2744     next = b->next;
2745     ierr = PetscFree(b->comps);CHKERRQ(ierr);
2746     ierr = PetscFree(b->ids);CHKERRQ(ierr);
2747     ierr = PetscFree(b->name);CHKERRQ(ierr);
2748     ierr = PetscFree(b->labelname);CHKERRQ(ierr);
2749     ierr = PetscFree(b);CHKERRQ(ierr);
2750   }
2751   lastnext = &(probB->boundary);
2752   for (b = probA->boundary; b; b = b->next) {
2753     DSBoundary bNew;
2754 
2755     ierr = PetscNew(&bNew);CHKERRQ(ierr);
2756     bNew->numcomps = b->numcomps;
2757     ierr = PetscMalloc1(bNew->numcomps, &bNew->comps);CHKERRQ(ierr);
2758     ierr = PetscMemcpy(bNew->comps, b->comps, bNew->numcomps*sizeof(PetscInt));CHKERRQ(ierr);
2759     bNew->numids = b->numids;
2760     ierr = PetscMalloc1(bNew->numids, &bNew->ids);CHKERRQ(ierr);
2761     ierr = PetscMemcpy(bNew->ids, b->ids, bNew->numids*sizeof(PetscInt));CHKERRQ(ierr);
2762     ierr = PetscStrallocpy(b->labelname,(char **) &(bNew->labelname));CHKERRQ(ierr);
2763     ierr = PetscStrallocpy(b->name,(char **) &(bNew->name));CHKERRQ(ierr);
2764     bNew->ctx   = b->ctx;
2765     bNew->type  = b->type;
2766     bNew->field = b->field;
2767     bNew->func  = b->func;
2768 
2769     *lastnext = bNew;
2770     lastnext = &(bNew->next);
2771   }
2772   PetscFunctionReturn(0);
2773 }
2774 
2775 /*@
2776   PetscDSCopyEquations - Copy all pointwise function pointers to the new problem
2777 
2778   Not collective
2779 
2780   Input Parameter:
2781 . prob - The PetscDS object
2782 
2783   Output Parameter:
2784 . newprob - The PetscDS copy
2785 
2786   Level: intermediate
2787 
2788 .seealso: PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
2789 @*/
2790 PetscErrorCode PetscDSCopyEquations(PetscDS prob, PetscDS newprob)
2791 {
2792   PetscInt       Nf, Ng, f, g;
2793   PetscErrorCode ierr;
2794 
2795   PetscFunctionBegin;
2796   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2797   PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 2);
2798   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
2799   ierr = PetscDSGetNumFields(newprob, &Ng);CHKERRQ(ierr);
2800   if (Nf != Ng) SETERRQ2(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_SIZ, "Number of fields must match %D != %D", Nf, Ng);
2801   for (f = 0; f < Nf; ++f) {
2802     PetscPointFunc   obj;
2803     PetscPointFunc   f0, f1;
2804     PetscPointJac    g0, g1, g2, g3;
2805     PetscBdPointFunc f0Bd, f1Bd;
2806     PetscBdPointJac  g0Bd, g1Bd, g2Bd, g3Bd;
2807     PetscRiemannFunc r;
2808 
2809     ierr = PetscDSGetObjective(prob, f, &obj);CHKERRQ(ierr);
2810     ierr = PetscDSGetResidual(prob, f, &f0, &f1);CHKERRQ(ierr);
2811     ierr = PetscDSGetBdResidual(prob, f, &f0Bd, &f1Bd);CHKERRQ(ierr);
2812     ierr = PetscDSGetRiemannSolver(prob, f, &r);CHKERRQ(ierr);
2813     ierr = PetscDSSetObjective(newprob, f, obj);CHKERRQ(ierr);
2814     ierr = PetscDSSetResidual(newprob, f, f0, f1);CHKERRQ(ierr);
2815     ierr = PetscDSSetBdResidual(newprob, f, f0Bd, f1Bd);CHKERRQ(ierr);
2816     ierr = PetscDSSetRiemannSolver(newprob, f, r);CHKERRQ(ierr);
2817     for (g = 0; g < Nf; ++g) {
2818       ierr = PetscDSGetJacobian(prob, f, g, &g0, &g1, &g2, &g3);CHKERRQ(ierr);
2819       ierr = PetscDSGetBdJacobian(prob, f, g, &g0Bd, &g1Bd, &g2Bd, &g3Bd);CHKERRQ(ierr);
2820       ierr = PetscDSSetJacobian(newprob, f, g, g0, g1, g2, g3);CHKERRQ(ierr);
2821       ierr = PetscDSSetBdJacobian(newprob, f, g, g0Bd, g1Bd, g2Bd, g3Bd);CHKERRQ(ierr);
2822     }
2823   }
2824   PetscFunctionReturn(0);
2825 }
2826 
2827 static PetscErrorCode PetscDSDestroy_Basic(PetscDS prob)
2828 {
2829   PetscErrorCode      ierr;
2830 
2831   PetscFunctionBegin;
2832   ierr = PetscFree(prob->data);CHKERRQ(ierr);
2833   PetscFunctionReturn(0);
2834 }
2835 
2836 static PetscErrorCode PetscDSInitialize_Basic(PetscDS prob)
2837 {
2838   PetscFunctionBegin;
2839   prob->ops->setfromoptions = NULL;
2840   prob->ops->setup          = NULL;
2841   prob->ops->view           = NULL;
2842   prob->ops->destroy        = PetscDSDestroy_Basic;
2843   PetscFunctionReturn(0);
2844 }
2845 
2846 /*MC
2847   PETSCDSBASIC = "basic" - A discrete system with pointwise residual and boundary residual functions
2848 
2849   Level: intermediate
2850 
2851 .seealso: PetscDSType, PetscDSCreate(), PetscDSSetType()
2852 M*/
2853 
2854 PETSC_EXTERN PetscErrorCode PetscDSCreate_Basic(PetscDS prob)
2855 {
2856   PetscDS_Basic *b;
2857   PetscErrorCode      ierr;
2858 
2859   PetscFunctionBegin;
2860   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2861   ierr       = PetscNewLog(prob, &b);CHKERRQ(ierr);
2862   prob->data = b;
2863 
2864   ierr = PetscDSInitialize_Basic(prob);CHKERRQ(ierr);
2865   PetscFunctionReturn(0);
2866 }
2867