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