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