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