xref: /petsc/src/dm/dt/interface/dtds.c (revision 8aefec70bf72ef1dffeff2fde7d501d2a2f792dc)
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 /* A PetscDS (Discrete System) encodes a set of equations posed in a discrete space, which represents a set of
9    nonlinear continuum equations. The equations can have multiple fields, each field having a different
10    discretization. In addition, different pieces of the domain can have different field combinations and equations.
11 
12    The DS provides the user a description of the approximation space on any given cell. It also gives pointwise
13    functions representing the equations.
14 
15    Each field is associated with a label, marking the cells on which it is supported. Note that a field can be
16    supported on the closure of a cell not in the label due to overlap of the boundary of neighboring cells. The DM
17    then creates a DS for each set of cells with identical approximation spaces. When assembling, the user asks for
18    the space associated with a given cell. DMPlex uses the labels associated with each DS in the default integration loop.
19 */
20 
21 /*@C
22   PetscDSRegister - Adds a new PetscDS implementation
23 
24   Not Collective
25 
26   Input Parameters:
27 + name        - The name of a new user-defined creation routine
28 - create_func - The creation routine itself
29 
30   Notes:
31   PetscDSRegister() may be called multiple times to add several user-defined PetscDSs
32 
33   Sample usage:
34 .vb
35     PetscDSRegister("my_ds", MyPetscDSCreate);
36 .ve
37 
38   Then, your PetscDS type can be chosen with the procedural interface via
39 .vb
40     PetscDSCreate(MPI_Comm, PetscDS *);
41     PetscDSSetType(PetscDS, "my_ds");
42 .ve
43    or at runtime via the option
44 .vb
45     -petscds_type my_ds
46 .ve
47 
48   Level: advanced
49 
50    Not available from Fortran
51 
52 .seealso: PetscDSRegisterAll(), PetscDSRegisterDestroy()
53 
54 @*/
55 PetscErrorCode PetscDSRegister(const char sname[], PetscErrorCode (*function)(PetscDS))
56 {
57   PetscErrorCode ierr;
58 
59   PetscFunctionBegin;
60   ierr = PetscFunctionListAdd(&PetscDSList, sname, function);CHKERRQ(ierr);
61   PetscFunctionReturn(0);
62 }
63 
64 /*@C
65   PetscDSSetType - Builds a particular PetscDS
66 
67   Collective on prob
68 
69   Input Parameters:
70 + prob - The PetscDS object
71 - name - The kind of system
72 
73   Options Database Key:
74 . -petscds_type <type> - Sets the PetscDS type; use -help for a list of available types
75 
76   Level: intermediate
77 
78    Not available from Fortran
79 
80 .seealso: PetscDSGetType(), PetscDSCreate()
81 @*/
82 PetscErrorCode PetscDSSetType(PetscDS prob, PetscDSType name)
83 {
84   PetscErrorCode (*r)(PetscDS);
85   PetscBool      match;
86   PetscErrorCode ierr;
87 
88   PetscFunctionBegin;
89   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
90   ierr = PetscObjectTypeCompare((PetscObject) prob, name, &match);CHKERRQ(ierr);
91   if (match) PetscFunctionReturn(0);
92 
93   ierr = PetscDSRegisterAll();CHKERRQ(ierr);
94   ierr = PetscFunctionListFind(PetscDSList, name, &r);CHKERRQ(ierr);
95   if (!r) SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDS type: %s", name);
96 
97   if (prob->ops->destroy) {
98     ierr             = (*prob->ops->destroy)(prob);CHKERRQ(ierr);
99     prob->ops->destroy = NULL;
100   }
101   ierr = (*r)(prob);CHKERRQ(ierr);
102   ierr = PetscObjectChangeTypeName((PetscObject) prob, name);CHKERRQ(ierr);
103   PetscFunctionReturn(0);
104 }
105 
106 /*@C
107   PetscDSGetType - Gets the PetscDS type name (as a string) from the object.
108 
109   Not Collective
110 
111   Input Parameter:
112 . prob  - The PetscDS
113 
114   Output Parameter:
115 . name - The PetscDS type name
116 
117   Level: intermediate
118 
119    Not available from Fortran
120 
121 .seealso: PetscDSSetType(), PetscDSCreate()
122 @*/
123 PetscErrorCode PetscDSGetType(PetscDS prob, PetscDSType *name)
124 {
125   PetscErrorCode ierr;
126 
127   PetscFunctionBegin;
128   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
129   PetscValidPointer(name, 2);
130   ierr = PetscDSRegisterAll();CHKERRQ(ierr);
131   *name = ((PetscObject) prob)->type_name;
132   PetscFunctionReturn(0);
133 }
134 
135 static PetscErrorCode PetscDSView_Ascii(PetscDS prob, PetscViewer viewer)
136 {
137   PetscViewerFormat  format;
138   const PetscScalar *constants;
139   PetscInt           numConstants, f;
140   PetscErrorCode     ierr;
141 
142   PetscFunctionBegin;
143   ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
144   ierr = PetscViewerASCIIPrintf(viewer, "Discrete System with %d fields\n", prob->Nf);CHKERRQ(ierr);
145   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
146   ierr = PetscViewerASCIIPrintf(viewer, "  cell total dim %D total comp %D\n", prob->totDim, prob->totComp);CHKERRQ(ierr);
147   if (prob->isHybrid) {ierr = PetscViewerASCIIPrintf(viewer, "  hybrid cell\n");CHKERRQ(ierr);}
148   for (f = 0; f < prob->Nf; ++f) {
149     DSBoundary      b;
150     PetscObject     obj;
151     PetscClassId    id;
152     PetscQuadrature q;
153     const char     *name;
154     PetscInt        Nc, Nq, Nqc;
155 
156     ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr);
157     ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
158     ierr = PetscObjectGetName(obj, &name);CHKERRQ(ierr);
159     ierr = PetscViewerASCIIPrintf(viewer, "Field %s", name ? name : "<unknown>");CHKERRQ(ierr);
160     ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr);
161     if (id == PETSCFE_CLASSID)      {
162       ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);
163       ierr = PetscFEGetQuadrature((PetscFE) obj, &q);CHKERRQ(ierr);
164       ierr = PetscViewerASCIIPrintf(viewer, " FEM");CHKERRQ(ierr);
165     } else if (id == PETSCFV_CLASSID) {
166       ierr = PetscFVGetNumComponents((PetscFV) obj, &Nc);CHKERRQ(ierr);
167       ierr = PetscFVGetQuadrature((PetscFV) obj, &q);CHKERRQ(ierr);
168       ierr = PetscViewerASCIIPrintf(viewer, " FVM");CHKERRQ(ierr);
169     }
170     else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %D", f);
171     if (Nc > 1) {ierr = PetscViewerASCIIPrintf(viewer, " %D components", Nc);CHKERRQ(ierr);}
172     else        {ierr = PetscViewerASCIIPrintf(viewer, " %D component ", Nc);CHKERRQ(ierr);}
173     if (prob->implicit[f]) {ierr = PetscViewerASCIIPrintf(viewer, " (implicit)");CHKERRQ(ierr);}
174     else                   {ierr = PetscViewerASCIIPrintf(viewer, " (explicit)");CHKERRQ(ierr);}
175     if (q) {
176       ierr = PetscQuadratureGetData(q, NULL, &Nqc, &Nq, NULL, NULL);CHKERRQ(ierr);
177       ierr = PetscViewerASCIIPrintf(viewer, " (Nq %D Nqc %D)", Nq, Nqc);CHKERRQ(ierr);
178     }
179     ierr = PetscViewerASCIIPrintf(viewer, " %D-jet", prob->jetDegree[f]);CHKERRQ(ierr);
180     ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr);
181     ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr);
182     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
183     if (id == PETSCFE_CLASSID)      {ierr = PetscFEView((PetscFE) obj, viewer);CHKERRQ(ierr);}
184     else if (id == PETSCFV_CLASSID) {ierr = PetscFVView((PetscFV) obj, viewer);CHKERRQ(ierr);}
185     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
186 
187     for (b = prob->boundary; b; b = b->next) {
188       char     *name;
189       PetscInt  c, i;
190 
191       if (b->field != f) continue;
192       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
193       ierr = PetscViewerASCIIPrintf(viewer, "Boundary %s (%s) %s\n", b->name, b->lname, DMBoundaryConditionTypes[b->type]);CHKERRQ(ierr);
194       if (!b->Nc) {
195         ierr = PetscViewerASCIIPrintf(viewer, "  all components\n");CHKERRQ(ierr);
196       } else {
197         ierr = PetscViewerASCIIPrintf(viewer, "  components: ");CHKERRQ(ierr);
198         ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr);
199         for (c = 0; c < b->Nc; ++c) {
200           if (c > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);}
201           ierr = PetscViewerASCIIPrintf(viewer, "%D", b->comps[c]);CHKERRQ(ierr);
202         }
203         ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr);
204         ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr);
205       }
206       ierr = PetscViewerASCIIPrintf(viewer, "  values: ");CHKERRQ(ierr);
207       ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr);
208       for (i = 0; i < b->Nv; ++i) {
209         if (i > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);}
210         ierr = PetscViewerASCIIPrintf(viewer, "%D", b->values[i]);CHKERRQ(ierr);
211       }
212       ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr);
213       ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr);
214       if (b->func) {
215         ierr = PetscDLAddr(b->func, &name);CHKERRQ(ierr);
216         if (name) {ierr = PetscViewerASCIIPrintf(viewer, "  func: %s\n", name);CHKERRQ(ierr);}
217         else      {ierr = PetscViewerASCIIPrintf(viewer, "  func: %p\n", b->func);CHKERRQ(ierr);}
218         ierr = PetscFree(name);CHKERRQ(ierr);
219       }
220       if (b->func_t) {
221         ierr = PetscDLAddr(b->func_t, &name);CHKERRQ(ierr);
222         if (name) {ierr = PetscViewerASCIIPrintf(viewer, "  func_t: %s\n", name);CHKERRQ(ierr);}
223         else      {ierr = PetscViewerASCIIPrintf(viewer, "  func_t: %p\n", b->func_t);CHKERRQ(ierr);}
224         ierr = PetscFree(name);CHKERRQ(ierr);
225       }
226       ierr = PetscWeakFormView(b->wf, viewer);CHKERRQ(ierr);
227       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
228     }
229   }
230   ierr = PetscDSGetConstants(prob, &numConstants, &constants);CHKERRQ(ierr);
231   if (numConstants) {
232     ierr = PetscViewerASCIIPrintf(viewer, "%D constants\n", numConstants);CHKERRQ(ierr);
233     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
234     for (f = 0; f < numConstants; ++f) {ierr = PetscViewerASCIIPrintf(viewer, "%g\n", (double) PetscRealPart(constants[f]));CHKERRQ(ierr);}
235     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
236   }
237   ierr = PetscWeakFormView(prob->wf, viewer);CHKERRQ(ierr);
238   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
239   PetscFunctionReturn(0);
240 }
241 
242 /*@C
243    PetscDSViewFromOptions - View from Options
244 
245    Collective on PetscDS
246 
247    Input Parameters:
248 +  A - the PetscDS object
249 .  obj - Optional object
250 -  name - command line option
251 
252    Level: intermediate
253 .seealso:  PetscDS, PetscDSView, PetscObjectViewFromOptions(), PetscDSCreate()
254 @*/
255 PetscErrorCode  PetscDSViewFromOptions(PetscDS A,PetscObject obj,const char name[])
256 {
257   PetscErrorCode ierr;
258 
259   PetscFunctionBegin;
260   PetscValidHeaderSpecific(A,PETSCDS_CLASSID,1);
261   ierr = PetscObjectViewFromOptions((PetscObject)A,obj,name);CHKERRQ(ierr);
262   PetscFunctionReturn(0);
263 }
264 
265 /*@C
266   PetscDSView - Views a PetscDS
267 
268   Collective on prob
269 
270   Input Parameter:
271 + prob - the PetscDS object to view
272 - v  - the viewer
273 
274   Level: developer
275 
276 .seealso PetscDSDestroy()
277 @*/
278 PetscErrorCode PetscDSView(PetscDS prob, PetscViewer v)
279 {
280   PetscBool      iascii;
281   PetscErrorCode ierr;
282 
283   PetscFunctionBegin;
284   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
285   if (!v) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) prob), &v);CHKERRQ(ierr);}
286   else    {PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2);}
287   ierr = PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
288   if (iascii) {ierr = PetscDSView_Ascii(prob, v);CHKERRQ(ierr);}
289   if (prob->ops->view) {ierr = (*prob->ops->view)(prob, v);CHKERRQ(ierr);}
290   PetscFunctionReturn(0);
291 }
292 
293 /*@
294   PetscDSSetFromOptions - sets parameters in a PetscDS from the options database
295 
296   Collective on prob
297 
298   Input Parameter:
299 . prob - the PetscDS object to set options for
300 
301   Options Database:
302 + -petscds_type <type>     : Set the DS type
303 . -petscds_view <view opt> : View the DS
304 . -petscds_jac_pre         : Turn formation of a separate Jacobian preconditioner on and off
305 . -bc_<name> <ids>         : Specify a list of label ids for a boundary condition
306 - -bc_<name>_comp <comps>  : Specify a list of field components to constrain for a boundary condition
307 
308   Level: developer
309 
310 .seealso PetscDSView()
311 @*/
312 PetscErrorCode PetscDSSetFromOptions(PetscDS prob)
313 {
314   DSBoundary     b;
315   const char    *defaultType;
316   char           name[256];
317   PetscBool      flg;
318   PetscErrorCode ierr;
319 
320   PetscFunctionBegin;
321   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
322   if (!((PetscObject) prob)->type_name) {
323     defaultType = PETSCDSBASIC;
324   } else {
325     defaultType = ((PetscObject) prob)->type_name;
326   }
327   ierr = PetscDSRegisterAll();CHKERRQ(ierr);
328 
329   ierr = PetscObjectOptionsBegin((PetscObject) prob);CHKERRQ(ierr);
330   for (b = prob->boundary; b; b = b->next) {
331     char       optname[1024];
332     PetscInt   ids[1024], len = 1024;
333     PetscBool  flg;
334 
335     ierr = PetscSNPrintf(optname, sizeof(optname), "-bc_%s", b->name);CHKERRQ(ierr);
336     ierr = PetscMemzero(ids, sizeof(ids));CHKERRQ(ierr);
337     ierr = PetscOptionsIntArray(optname, "List of boundary IDs", "", ids, &len, &flg);CHKERRQ(ierr);
338     if (flg) {
339       b->Nv = len;
340       ierr = PetscFree(b->values);CHKERRQ(ierr);
341       ierr = PetscMalloc1(len, &b->values);CHKERRQ(ierr);
342       ierr = PetscArraycpy(b->values, ids, len);CHKERRQ(ierr);
343       ierr = PetscWeakFormRewriteKeys(b->wf, b->label, len, b->values);CHKERRQ(ierr);
344     }
345     len = 1024;
346     ierr = PetscSNPrintf(optname, sizeof(optname), "-bc_%s_comp", b->name);CHKERRQ(ierr);
347     ierr = PetscMemzero(ids, sizeof(ids));CHKERRQ(ierr);
348     ierr = PetscOptionsIntArray(optname, "List of boundary field components", "", ids, &len, &flg);CHKERRQ(ierr);
349     if (flg) {
350       b->Nc = len;
351       ierr = PetscFree(b->comps);CHKERRQ(ierr);
352       ierr = PetscMalloc1(len, &b->comps);CHKERRQ(ierr);
353       ierr = PetscArraycpy(b->comps, ids, len);CHKERRQ(ierr);
354     }
355   }
356   ierr = PetscOptionsFList("-petscds_type", "Discrete System", "PetscDSSetType", PetscDSList, defaultType, name, 256, &flg);CHKERRQ(ierr);
357   if (flg) {
358     ierr = PetscDSSetType(prob, name);CHKERRQ(ierr);
359   } else if (!((PetscObject) prob)->type_name) {
360     ierr = PetscDSSetType(prob, defaultType);CHKERRQ(ierr);
361   }
362   ierr = PetscOptionsBool("-petscds_jac_pre", "Discrete System", "PetscDSUseJacobianPreconditioner", prob->useJacPre, &prob->useJacPre, &flg);CHKERRQ(ierr);
363   if (prob->ops->setfromoptions) {ierr = (*prob->ops->setfromoptions)(prob);CHKERRQ(ierr);}
364   /* process any options handlers added with PetscObjectAddOptionsHandler() */
365   ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) prob);CHKERRQ(ierr);
366   ierr = PetscOptionsEnd();CHKERRQ(ierr);
367   if (prob->Nf) {ierr = PetscDSViewFromOptions(prob, NULL, "-petscds_view");CHKERRQ(ierr);}
368   PetscFunctionReturn(0);
369 }
370 
371 /*@C
372   PetscDSSetUp - Construct data structures for the PetscDS
373 
374   Collective on prob
375 
376   Input Parameter:
377 . prob - the PetscDS object to setup
378 
379   Level: developer
380 
381 .seealso PetscDSView(), PetscDSDestroy()
382 @*/
383 PetscErrorCode PetscDSSetUp(PetscDS prob)
384 {
385   const PetscInt Nf   = prob->Nf;
386   PetscBool      hasH = PETSC_FALSE;
387   PetscInt       dim, dimEmbed, NbMax = 0, NcMax = 0, NqMax = 0, NsMax = 1, f;
388   PetscErrorCode ierr;
389 
390   PetscFunctionBegin;
391   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
392   if (prob->setup) PetscFunctionReturn(0);
393   /* Calculate sizes */
394   ierr = PetscDSGetSpatialDimension(prob, &dim);CHKERRQ(ierr);
395   ierr = PetscDSGetCoordinateDimension(prob, &dimEmbed);CHKERRQ(ierr);
396   prob->totDim = prob->totComp = 0;
397   ierr = PetscMalloc2(Nf,&prob->Nc,Nf,&prob->Nb);CHKERRQ(ierr);
398   ierr = PetscCalloc2(Nf+1,&prob->off,Nf+1,&prob->offDer);CHKERRQ(ierr);
399   ierr = PetscMalloc2(Nf,&prob->T,Nf,&prob->Tf);CHKERRQ(ierr);
400   for (f = 0; f < Nf; ++f) {
401     PetscObject     obj;
402     PetscClassId    id;
403     PetscQuadrature q = NULL;
404     PetscInt        Nq = 0, Nb, Nc;
405 
406     ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr);
407     if (prob->jetDegree[f] > 1) hasH = PETSC_TRUE;
408     if (!obj) {
409       /* Empty mesh */
410       Nb = Nc = 0;
411       prob->T[f] = prob->Tf[f] = NULL;
412     } else {
413       ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
414       if (id == PETSCFE_CLASSID)      {
415         PetscFE fe = (PetscFE) obj;
416 
417         ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr);
418         ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr);
419         ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr);
420         ierr = PetscFEGetCellTabulation(fe, prob->jetDegree[f], &prob->T[f]);CHKERRQ(ierr);
421         ierr = PetscFEGetFaceTabulation(fe, prob->jetDegree[f], &prob->Tf[f]);CHKERRQ(ierr);
422       } else if (id == PETSCFV_CLASSID) {
423         PetscFV fv = (PetscFV) obj;
424 
425         ierr = PetscFVGetQuadrature(fv, &q);CHKERRQ(ierr);
426         ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr);
427         Nb   = Nc;
428         ierr = PetscFVGetCellTabulation(fv, &prob->T[f]);CHKERRQ(ierr);
429         /* TODO: should PetscFV also have face tabulation? Otherwise there will be a null pointer in prob->basisFace */
430       } else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f);
431     }
432     prob->Nc[f]       = Nc;
433     prob->Nb[f]       = Nb;
434     prob->off[f+1]    = Nc     + prob->off[f];
435     prob->offDer[f+1] = Nc*dim + prob->offDer[f];
436     if (q) {ierr = PetscQuadratureGetData(q, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr);}
437     NqMax          = PetscMax(NqMax, Nq);
438     NbMax          = PetscMax(NbMax, Nb);
439     NcMax          = PetscMax(NcMax, Nc);
440     prob->totDim  += Nb;
441     prob->totComp += Nc;
442     /* There are two faces for all fields but the cohesive field on a hybrid cell */
443     if (prob->isHybrid && (f < Nf-1)) prob->totDim += Nb;
444   }
445   /* Allocate works space */
446   NsMax = 2; /* Even non-hybrid discretizations can be used in a hybrid integration, so we need this extra workspace */
447   ierr = PetscMalloc3(NsMax*prob->totComp,&prob->u,NsMax*prob->totComp,&prob->u_t,NsMax*prob->totComp*dimEmbed + (hasH ? NsMax*prob->totComp*dimEmbed*dimEmbed : 0),&prob->u_x);CHKERRQ(ierr);
448   ierr = PetscMalloc5(dimEmbed,&prob->x,NbMax*NcMax,&prob->basisReal,NbMax*NcMax*dimEmbed,&prob->basisDerReal,NbMax*NcMax,&prob->testReal,NbMax*NcMax*dimEmbed,&prob->testDerReal);CHKERRQ(ierr);
449   ierr = PetscMalloc6(NsMax*NqMax*NcMax,&prob->f0,NsMax*NqMax*NcMax*dimEmbed,&prob->f1,
450                       NsMax*NsMax*NqMax*NcMax*NcMax,&prob->g0,NsMax*NsMax*NqMax*NcMax*NcMax*dimEmbed,&prob->g1,
451                       NsMax*NsMax*NqMax*NcMax*NcMax*dimEmbed,&prob->g2,NsMax*NsMax*NqMax*NcMax*NcMax*dimEmbed*dimEmbed,&prob->g3);CHKERRQ(ierr);
452   if (prob->ops->setup) {ierr = (*prob->ops->setup)(prob);CHKERRQ(ierr);}
453   prob->setup = PETSC_TRUE;
454   PetscFunctionReturn(0);
455 }
456 
457 static PetscErrorCode PetscDSDestroyStructs_Static(PetscDS prob)
458 {
459   PetscErrorCode ierr;
460 
461   PetscFunctionBegin;
462   ierr = PetscFree2(prob->Nc,prob->Nb);CHKERRQ(ierr);
463   ierr = PetscFree2(prob->off,prob->offDer);CHKERRQ(ierr);
464   ierr = PetscFree2(prob->T,prob->Tf);CHKERRQ(ierr);
465   ierr = PetscFree3(prob->u,prob->u_t,prob->u_x);CHKERRQ(ierr);
466   ierr = PetscFree5(prob->x,prob->basisReal, prob->basisDerReal,prob->testReal,prob->testDerReal);CHKERRQ(ierr);
467   ierr = PetscFree6(prob->f0,prob->f1,prob->g0,prob->g1,prob->g2,prob->g3);CHKERRQ(ierr);
468   PetscFunctionReturn(0);
469 }
470 
471 static PetscErrorCode PetscDSEnlarge_Static(PetscDS prob, PetscInt NfNew)
472 {
473   PetscObject      *tmpd;
474   PetscBool        *tmpi;
475   PetscInt         *tmpk;
476   PetscPointFunc   *tmpup;
477   PetscSimplePointFunc *tmpexactSol,  *tmpexactSol_t;
478   void                **tmpexactCtx, **tmpexactCtx_t;
479   void            **tmpctx;
480   PetscInt          Nf = prob->Nf, f;
481   PetscErrorCode    ierr;
482 
483   PetscFunctionBegin;
484   if (Nf >= NfNew) PetscFunctionReturn(0);
485   prob->setup = PETSC_FALSE;
486   ierr = PetscDSDestroyStructs_Static(prob);CHKERRQ(ierr);
487   ierr = PetscMalloc3(NfNew, &tmpd, NfNew, &tmpi, NfNew, &tmpk);CHKERRQ(ierr);
488   for (f = 0; f < Nf; ++f) {tmpd[f] = prob->disc[f]; tmpi[f] = prob->implicit[f]; tmpk[f] = prob->jetDegree[f];}
489   for (f = Nf; f < NfNew; ++f) {tmpd[f] = NULL; tmpi[f] = PETSC_TRUE; tmpk[f] = 1;}
490   ierr = PetscFree3(prob->disc, prob->implicit, prob->jetDegree);CHKERRQ(ierr);
491   ierr = PetscWeakFormSetNumFields(prob->wf, NfNew);CHKERRQ(ierr);
492   prob->Nf        = NfNew;
493   prob->disc      = tmpd;
494   prob->implicit  = tmpi;
495   prob->jetDegree = tmpk;
496   ierr = PetscCalloc2(NfNew, &tmpup, NfNew, &tmpctx);CHKERRQ(ierr);
497   for (f = 0; f < Nf; ++f) tmpup[f] = prob->update[f];
498   for (f = 0; f < Nf; ++f) tmpctx[f] = prob->ctx[f];
499   for (f = Nf; f < NfNew; ++f) tmpup[f] = NULL;
500   for (f = Nf; f < NfNew; ++f) tmpctx[f] = NULL;
501   ierr = PetscFree2(prob->update, prob->ctx);CHKERRQ(ierr);
502   prob->update = tmpup;
503   prob->ctx = tmpctx;
504   ierr = PetscCalloc4(NfNew, &tmpexactSol, NfNew, &tmpexactCtx, NfNew, &tmpexactSol_t, NfNew, &tmpexactCtx_t);CHKERRQ(ierr);
505   for (f = 0; f < Nf; ++f) tmpexactSol[f] = prob->exactSol[f];
506   for (f = 0; f < Nf; ++f) tmpexactCtx[f] = prob->exactCtx[f];
507   for (f = 0; f < Nf; ++f) tmpexactSol_t[f] = prob->exactSol_t[f];
508   for (f = 0; f < Nf; ++f) tmpexactCtx_t[f] = prob->exactCtx_t[f];
509   for (f = Nf; f < NfNew; ++f) tmpexactSol[f] = NULL;
510   for (f = Nf; f < NfNew; ++f) tmpexactCtx[f] = NULL;
511   for (f = Nf; f < NfNew; ++f) tmpexactSol_t[f] = NULL;
512   for (f = Nf; f < NfNew; ++f) tmpexactCtx_t[f] = NULL;
513   ierr = PetscFree4(prob->exactSol, prob->exactCtx, prob->exactSol_t, prob->exactCtx_t);CHKERRQ(ierr);
514   prob->exactSol = tmpexactSol;
515   prob->exactCtx = tmpexactCtx;
516   prob->exactSol_t = tmpexactSol_t;
517   prob->exactCtx_t = tmpexactCtx_t;
518   PetscFunctionReturn(0);
519 }
520 
521 /*@
522   PetscDSDestroy - Destroys a PetscDS object
523 
524   Collective on prob
525 
526   Input Parameter:
527 . prob - the PetscDS object to destroy
528 
529   Level: developer
530 
531 .seealso PetscDSView()
532 @*/
533 PetscErrorCode PetscDSDestroy(PetscDS *ds)
534 {
535   PetscInt       f;
536   PetscErrorCode ierr;
537 
538   PetscFunctionBegin;
539   if (!*ds) PetscFunctionReturn(0);
540   PetscValidHeaderSpecific((*ds), PETSCDS_CLASSID, 1);
541 
542   if (--((PetscObject)(*ds))->refct > 0) {*ds = NULL; PetscFunctionReturn(0);}
543   ((PetscObject) (*ds))->refct = 0;
544   if ((*ds)->subprobs) {
545     PetscInt dim, d;
546 
547     ierr = PetscDSGetSpatialDimension(*ds, &dim);CHKERRQ(ierr);
548     for (d = 0; d < dim; ++d) {ierr = PetscDSDestroy(&(*ds)->subprobs[d]);CHKERRQ(ierr);}
549   }
550   ierr = PetscFree((*ds)->subprobs);CHKERRQ(ierr);
551   ierr = PetscDSDestroyStructs_Static(*ds);CHKERRQ(ierr);
552   for (f = 0; f < (*ds)->Nf; ++f) {
553     ierr = PetscObjectDereference((*ds)->disc[f]);CHKERRQ(ierr);
554   }
555   ierr = PetscFree3((*ds)->disc, (*ds)->implicit, (*ds)->jetDegree);CHKERRQ(ierr);
556   ierr = PetscWeakFormDestroy(&(*ds)->wf);CHKERRQ(ierr);
557   ierr = PetscFree2((*ds)->update,(*ds)->ctx);CHKERRQ(ierr);
558   ierr = PetscFree4((*ds)->exactSol,(*ds)->exactCtx,(*ds)->exactSol_t,(*ds)->exactCtx_t);CHKERRQ(ierr);
559   if ((*ds)->ops->destroy) {ierr = (*(*ds)->ops->destroy)(*ds);CHKERRQ(ierr);}
560   ierr = PetscDSDestroyBoundary(*ds);CHKERRQ(ierr);
561   ierr = PetscFree((*ds)->constants);CHKERRQ(ierr);
562   ierr = PetscHeaderDestroy(ds);CHKERRQ(ierr);
563   PetscFunctionReturn(0);
564 }
565 
566 /*@
567   PetscDSCreate - Creates an empty PetscDS object. The type can then be set with PetscDSSetType().
568 
569   Collective
570 
571   Input Parameter:
572 . comm - The communicator for the PetscDS object
573 
574   Output Parameter:
575 . ds   - The PetscDS object
576 
577   Level: beginner
578 
579 .seealso: PetscDSSetType(), PETSCDSBASIC
580 @*/
581 PetscErrorCode PetscDSCreate(MPI_Comm comm, PetscDS *ds)
582 {
583   PetscDS        p;
584   PetscErrorCode ierr;
585 
586   PetscFunctionBegin;
587   PetscValidPointer(ds, 2);
588   *ds  = NULL;
589   ierr = PetscDSInitializePackage();CHKERRQ(ierr);
590 
591   ierr = PetscHeaderCreate(p, PETSCDS_CLASSID, "PetscDS", "Discrete System", "PetscDS", comm, PetscDSDestroy, PetscDSView);CHKERRQ(ierr);
592 
593   p->Nf           = 0;
594   p->setup        = PETSC_FALSE;
595   p->numConstants = 0;
596   p->constants    = NULL;
597   p->dimEmbed     = -1;
598   p->useJacPre    = PETSC_TRUE;
599   ierr = PetscWeakFormCreate(comm, &p->wf);CHKERRQ(ierr);
600 
601   *ds = p;
602   PetscFunctionReturn(0);
603 }
604 
605 /*@
606   PetscDSGetNumFields - Returns the number of fields in the DS
607 
608   Not collective
609 
610   Input Parameter:
611 . prob - The PetscDS object
612 
613   Output Parameter:
614 . Nf - The number of fields
615 
616   Level: beginner
617 
618 .seealso: PetscDSGetSpatialDimension(), PetscDSCreate()
619 @*/
620 PetscErrorCode PetscDSGetNumFields(PetscDS prob, PetscInt *Nf)
621 {
622   PetscFunctionBegin;
623   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
624   PetscValidPointer(Nf, 2);
625   *Nf = prob->Nf;
626   PetscFunctionReturn(0);
627 }
628 
629 /*@
630   PetscDSGetSpatialDimension - Returns the spatial dimension of the DS, meaning the topological dimension of the discretizations
631 
632   Not collective
633 
634   Input Parameter:
635 . prob - The PetscDS object
636 
637   Output Parameter:
638 . dim - The spatial dimension
639 
640   Level: beginner
641 
642 .seealso: PetscDSGetCoordinateDimension(), PetscDSGetNumFields(), PetscDSCreate()
643 @*/
644 PetscErrorCode PetscDSGetSpatialDimension(PetscDS prob, PetscInt *dim)
645 {
646   PetscErrorCode ierr;
647 
648   PetscFunctionBegin;
649   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
650   PetscValidPointer(dim, 2);
651   *dim = 0;
652   if (prob->Nf) {
653     PetscObject  obj;
654     PetscClassId id;
655 
656     ierr = PetscDSGetDiscretization(prob, 0, &obj);CHKERRQ(ierr);
657     if (obj) {
658       ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
659       if (id == PETSCFE_CLASSID)      {ierr = PetscFEGetSpatialDimension((PetscFE) obj, dim);CHKERRQ(ierr);}
660       else if (id == PETSCFV_CLASSID) {ierr = PetscFVGetSpatialDimension((PetscFV) obj, dim);CHKERRQ(ierr);}
661       else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
662     }
663   }
664   PetscFunctionReturn(0);
665 }
666 
667 /*@
668   PetscDSGetCoordinateDimension - Returns the coordinate dimension of the DS, meaning the dimension of the space into which the discretiaztions are embedded
669 
670   Not collective
671 
672   Input Parameter:
673 . prob - The PetscDS object
674 
675   Output Parameter:
676 . dimEmbed - The coordinate dimension
677 
678   Level: beginner
679 
680 .seealso: PetscDSSetCoordinateDimension(), PetscDSGetSpatialDimension(), PetscDSGetNumFields(), PetscDSCreate()
681 @*/
682 PetscErrorCode PetscDSGetCoordinateDimension(PetscDS prob, PetscInt *dimEmbed)
683 {
684   PetscFunctionBegin;
685   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
686   PetscValidPointer(dimEmbed, 2);
687   if (prob->dimEmbed < 0) SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONGSTATE, "No coordinate dimension set for this DS");
688   *dimEmbed = prob->dimEmbed;
689   PetscFunctionReturn(0);
690 }
691 
692 /*@
693   PetscDSSetCoordinateDimension - Set the coordinate dimension of the DS, meaning the dimension of the space into which the discretiaztions are embedded
694 
695   Logically collective on prob
696 
697   Input Parameters:
698 + prob - The PetscDS object
699 - dimEmbed - The coordinate dimension
700 
701   Level: beginner
702 
703 .seealso: PetscDSGetCoordinateDimension(), PetscDSGetSpatialDimension(), PetscDSGetNumFields(), PetscDSCreate()
704 @*/
705 PetscErrorCode PetscDSSetCoordinateDimension(PetscDS prob, PetscInt dimEmbed)
706 {
707   PetscFunctionBegin;
708   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
709   if (dimEmbed < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate dimension must be non-negative, not %D", dimEmbed);
710   prob->dimEmbed = dimEmbed;
711   PetscFunctionReturn(0);
712 }
713 
714 /*@
715   PetscDSGetHybrid - Returns the flag for a hybrid (cohesive) cell
716 
717   Not collective
718 
719   Input Parameter:
720 . prob - The PetscDS object
721 
722   Output Parameter:
723 . isHybrid - The flag
724 
725   Level: developer
726 
727 .seealso: PetscDSSetHybrid(), PetscDSCreate()
728 @*/
729 PetscErrorCode PetscDSGetHybrid(PetscDS prob, PetscBool *isHybrid)
730 {
731   PetscFunctionBegin;
732   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
733   PetscValidPointer(isHybrid, 2);
734   *isHybrid = prob->isHybrid;
735   PetscFunctionReturn(0);
736 }
737 
738 /*@
739   PetscDSSetHybrid - Set the flag for a hybrid (cohesive) cell
740 
741   Not collective
742 
743   Input Parameters:
744 + prob - The PetscDS object
745 - isHybrid - The flag
746 
747   Level: developer
748 
749 .seealso: PetscDSGetHybrid(), PetscDSCreate()
750 @*/
751 PetscErrorCode PetscDSSetHybrid(PetscDS prob, PetscBool isHybrid)
752 {
753   PetscFunctionBegin;
754   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
755   prob->isHybrid = isHybrid;
756   PetscFunctionReturn(0);
757 }
758 
759 /*@
760   PetscDSGetTotalDimension - Returns the total size of the approximation space for this system
761 
762   Not collective
763 
764   Input Parameter:
765 . prob - The PetscDS object
766 
767   Output Parameter:
768 . dim - The total problem dimension
769 
770   Level: beginner
771 
772 .seealso: PetscDSGetNumFields(), PetscDSCreate()
773 @*/
774 PetscErrorCode PetscDSGetTotalDimension(PetscDS prob, PetscInt *dim)
775 {
776   PetscErrorCode ierr;
777 
778   PetscFunctionBegin;
779   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
780   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
781   PetscValidPointer(dim, 2);
782   *dim = prob->totDim;
783   PetscFunctionReturn(0);
784 }
785 
786 /*@
787   PetscDSGetTotalComponents - Returns the total number of components in this system
788 
789   Not collective
790 
791   Input Parameter:
792 . prob - The PetscDS object
793 
794   Output Parameter:
795 . dim - The total number of components
796 
797   Level: beginner
798 
799 .seealso: PetscDSGetNumFields(), PetscDSCreate()
800 @*/
801 PetscErrorCode PetscDSGetTotalComponents(PetscDS prob, PetscInt *Nc)
802 {
803   PetscErrorCode ierr;
804 
805   PetscFunctionBegin;
806   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
807   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
808   PetscValidPointer(Nc, 2);
809   *Nc = prob->totComp;
810   PetscFunctionReturn(0);
811 }
812 
813 /*@
814   PetscDSGetDiscretization - Returns the discretization object for the given field
815 
816   Not collective
817 
818   Input Parameters:
819 + prob - The PetscDS object
820 - f - The field number
821 
822   Output Parameter:
823 . disc - The discretization object
824 
825   Level: beginner
826 
827 .seealso: PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
828 @*/
829 PetscErrorCode PetscDSGetDiscretization(PetscDS prob, PetscInt f, PetscObject *disc)
830 {
831   PetscFunctionBeginHot;
832   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
833   PetscValidPointer(disc, 3);
834   if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf);
835   *disc = prob->disc[f];
836   PetscFunctionReturn(0);
837 }
838 
839 /*@
840   PetscDSSetDiscretization - Sets the discretization object for the given field
841 
842   Not collective
843 
844   Input Parameters:
845 + prob - The PetscDS object
846 . f - The field number
847 - disc - The discretization object
848 
849   Level: beginner
850 
851 .seealso: PetscDSGetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
852 @*/
853 PetscErrorCode PetscDSSetDiscretization(PetscDS prob, PetscInt f, PetscObject disc)
854 {
855   PetscErrorCode ierr;
856 
857   PetscFunctionBegin;
858   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
859   if (disc) PetscValidPointer(disc, 3);
860   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
861   ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr);
862   ierr = PetscObjectDereference(prob->disc[f]);CHKERRQ(ierr);
863   prob->disc[f] = disc;
864   ierr = PetscObjectReference(disc);CHKERRQ(ierr);
865   if (disc) {
866     PetscClassId id;
867 
868     ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr);
869     if (id == PETSCFE_CLASSID) {
870       ierr = PetscDSSetImplicit(prob, f, PETSC_TRUE);CHKERRQ(ierr);
871     } else if (id == PETSCFV_CLASSID) {
872       ierr = PetscDSSetImplicit(prob, f, PETSC_FALSE);CHKERRQ(ierr);
873     }
874     ierr = PetscDSSetJetDegree(prob, f, 1);CHKERRQ(ierr);
875   }
876   PetscFunctionReturn(0);
877 }
878 
879 /*@
880   PetscDSGetWeakForm - Returns the weak form object
881 
882   Not collective
883 
884   Input Parameter:
885 . ds - The PetscDS object
886 
887   Output Parameter:
888 . wf - The weak form object
889 
890   Level: beginner
891 
892 .seealso: PetscDSSetWeakForm(), PetscDSGetNumFields(), PetscDSCreate()
893 @*/
894 PetscErrorCode PetscDSGetWeakForm(PetscDS ds, PetscWeakForm *wf)
895 {
896   PetscFunctionBegin;
897   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
898   PetscValidPointer(wf, 2);
899   *wf = ds->wf;
900   PetscFunctionReturn(0);
901 }
902 
903 /*@
904   PetscDSSetWeakForm - Sets the weak form object
905 
906   Not collective
907 
908   Input Parameters:
909 + ds - The PetscDS object
910 - wf - The weak form object
911 
912   Level: beginner
913 
914 .seealso: PetscDSGetWeakForm(), PetscDSGetNumFields(), PetscDSCreate()
915 @*/
916 PetscErrorCode PetscDSSetWeakForm(PetscDS ds, PetscWeakForm wf)
917 {
918   PetscErrorCode ierr;
919 
920   PetscFunctionBegin;
921   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
922   PetscValidHeaderSpecific(wf, PETSCWEAKFORM_CLASSID, 2);
923   ierr = PetscObjectDereference((PetscObject) ds->wf);CHKERRQ(ierr);
924   ds->wf = wf;
925   ierr = PetscObjectReference((PetscObject) wf);CHKERRQ(ierr);
926   ierr = PetscWeakFormSetNumFields(wf, ds->Nf);CHKERRQ(ierr);
927   PetscFunctionReturn(0);
928 }
929 
930 /*@
931   PetscDSAddDiscretization - Adds a discretization object
932 
933   Not collective
934 
935   Input Parameters:
936 + prob - The PetscDS object
937 - disc - The boundary discretization object
938 
939   Level: beginner
940 
941 .seealso: PetscDSGetDiscretization(), PetscDSSetDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
942 @*/
943 PetscErrorCode PetscDSAddDiscretization(PetscDS prob, PetscObject disc)
944 {
945   PetscErrorCode ierr;
946 
947   PetscFunctionBegin;
948   ierr = PetscDSSetDiscretization(prob, prob->Nf, disc);CHKERRQ(ierr);
949   PetscFunctionReturn(0);
950 }
951 
952 /*@
953   PetscDSGetQuadrature - Returns the quadrature, which must agree for all fields in the DS
954 
955   Not collective
956 
957   Input Parameter:
958 . prob - The PetscDS object
959 
960   Output Parameter:
961 . q - The quadrature object
962 
963 Level: intermediate
964 
965 .seealso: PetscDSSetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
966 @*/
967 PetscErrorCode PetscDSGetQuadrature(PetscDS prob, PetscQuadrature *q)
968 {
969   PetscObject    obj;
970   PetscClassId   id;
971   PetscErrorCode ierr;
972 
973   PetscFunctionBegin;
974   *q = NULL;
975   if (!prob->Nf) PetscFunctionReturn(0);
976   ierr = PetscDSGetDiscretization(prob, 0, &obj);CHKERRQ(ierr);
977   ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
978   if      (id == PETSCFE_CLASSID) {ierr = PetscFEGetQuadrature((PetscFE) obj, q);CHKERRQ(ierr);}
979   else if (id == PETSCFV_CLASSID) {ierr = PetscFVGetQuadrature((PetscFV) obj, q);CHKERRQ(ierr);}
980   else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
981   PetscFunctionReturn(0);
982 }
983 
984 /*@
985   PetscDSGetImplicit - Returns the flag for implicit solve for this field. This is just a guide for IMEX
986 
987   Not collective
988 
989   Input Parameters:
990 + prob - The PetscDS object
991 - f - The field number
992 
993   Output Parameter:
994 . implicit - The flag indicating what kind of solve to use for this field
995 
996   Level: developer
997 
998 .seealso: PetscDSSetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
999 @*/
1000 PetscErrorCode PetscDSGetImplicit(PetscDS prob, PetscInt f, PetscBool *implicit)
1001 {
1002   PetscFunctionBegin;
1003   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1004   PetscValidPointer(implicit, 3);
1005   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);
1006   *implicit = prob->implicit[f];
1007   PetscFunctionReturn(0);
1008 }
1009 
1010 /*@
1011   PetscDSSetImplicit - Set the flag for implicit solve for this field. This is just a guide for IMEX
1012 
1013   Not collective
1014 
1015   Input Parameters:
1016 + prob - The PetscDS object
1017 . f - The field number
1018 - implicit - The flag indicating what kind of solve to use for this field
1019 
1020   Level: developer
1021 
1022 .seealso: PetscDSGetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
1023 @*/
1024 PetscErrorCode PetscDSSetImplicit(PetscDS prob, PetscInt f, PetscBool implicit)
1025 {
1026   PetscFunctionBegin;
1027   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1028   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);
1029   prob->implicit[f] = implicit;
1030   PetscFunctionReturn(0);
1031 }
1032 
1033 /*@
1034   PetscDSGetJetDegree - Returns the highest derivative for this field equation, or the k-jet that the discretization needs to tabulate.
1035 
1036   Not collective
1037 
1038   Input Parameters:
1039 + ds - The PetscDS object
1040 - f  - The field number
1041 
1042   Output Parameter:
1043 . k  - The highest derivative we need to tabulate
1044 
1045   Level: developer
1046 
1047 .seealso: PetscDSSetJetDegree(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
1048 @*/
1049 PetscErrorCode PetscDSGetJetDegree(PetscDS ds, PetscInt f, PetscInt *k)
1050 {
1051   PetscFunctionBegin;
1052   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1053   PetscValidPointer(k, 3);
1054   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
1055   *k = ds->jetDegree[f];
1056   PetscFunctionReturn(0);
1057 }
1058 
1059 /*@
1060   PetscDSSetJetDegree - Set the highest derivative for this field equation, or the k-jet that the discretization needs to tabulate.
1061 
1062   Not collective
1063 
1064   Input Parameters:
1065 + ds - The PetscDS object
1066 . f  - The field number
1067 - k  - The highest derivative we need to tabulate
1068 
1069   Level: developer
1070 
1071 .seealso: PetscDSGetJetDegree(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
1072 @*/
1073 PetscErrorCode PetscDSSetJetDegree(PetscDS ds, PetscInt f, PetscInt k)
1074 {
1075   PetscFunctionBegin;
1076   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1077   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
1078   ds->jetDegree[f] = k;
1079   PetscFunctionReturn(0);
1080 }
1081 
1082 PetscErrorCode PetscDSGetObjective(PetscDS ds, PetscInt f,
1083                                    void (**obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1084                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1085                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1086                                                 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]))
1087 {
1088   PetscPointFunc *tmp;
1089   PetscInt        n;
1090   PetscErrorCode  ierr;
1091 
1092   PetscFunctionBegin;
1093   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1094   PetscValidPointer(obj, 3);
1095   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
1096   ierr = PetscWeakFormGetObjective(ds->wf, NULL, 0, f, 0, &n, &tmp);CHKERRQ(ierr);
1097   *obj = tmp ? tmp[0] : NULL;
1098   PetscFunctionReturn(0);
1099 }
1100 
1101 PetscErrorCode PetscDSSetObjective(PetscDS ds, PetscInt f,
1102                                    void (*obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1103                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1104                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1105                                                PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]))
1106 {
1107   PetscErrorCode ierr;
1108 
1109   PetscFunctionBegin;
1110   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1111   if (obj) PetscValidFunction(obj, 3);
1112   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1113   ierr = PetscWeakFormSetIndexObjective(ds->wf, NULL, 0, f, 0, 0, obj);CHKERRQ(ierr);
1114   PetscFunctionReturn(0);
1115 }
1116 
1117 /*@C
1118   PetscDSGetResidual - Get the pointwise residual function for a given test field
1119 
1120   Not collective
1121 
1122   Input Parameters:
1123 + ds - The PetscDS
1124 - f  - The test field number
1125 
1126   Output Parameters:
1127 + f0 - integrand for the test function term
1128 - f1 - integrand for the test function gradient term
1129 
1130   Note: We are using a first order FEM model for the weak form:
1131 
1132   \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)
1133 
1134 The calling sequence for the callbacks f0 and f1 is given by:
1135 
1136 $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1137 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1138 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1139 $    PetscReal t, const PetscReal x[], PetscScalar f0[])
1140 
1141 + dim - the spatial dimension
1142 . Nf - the number of fields
1143 . uOff - the offset into u[] and u_t[] for each field
1144 . uOff_x - the offset into u_x[] for each field
1145 . u - each field evaluated at the current point
1146 . u_t - the time derivative of each field evaluated at the current point
1147 . u_x - the gradient of each field evaluated at the current point
1148 . aOff - the offset into a[] and a_t[] for each auxiliary field
1149 . aOff_x - the offset into a_x[] for each auxiliary field
1150 . a - each auxiliary field evaluated at the current point
1151 . a_t - the time derivative of each auxiliary field evaluated at the current point
1152 . a_x - the gradient of auxiliary each field evaluated at the current point
1153 . t - current time
1154 . x - coordinates of the current point
1155 . numConstants - number of constant parameters
1156 . constants - constant parameters
1157 - f0 - output values at the current point
1158 
1159   Level: intermediate
1160 
1161 .seealso: PetscDSSetResidual()
1162 @*/
1163 PetscErrorCode PetscDSGetResidual(PetscDS ds, PetscInt f,
1164                                   void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1165                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1166                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1167                                               PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
1168                                   void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1169                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1170                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1171                                               PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
1172 {
1173   PetscPointFunc *tmp0, *tmp1;
1174   PetscInt        n0, n1;
1175   PetscErrorCode  ierr;
1176 
1177   PetscFunctionBegin;
1178   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1179   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
1180   ierr = PetscWeakFormGetResidual(ds->wf, NULL, 0, f, 0, &n0, &tmp0, &n1, &tmp1);CHKERRQ(ierr);
1181   *f0  = tmp0 ? tmp0[0] : NULL;
1182   *f1  = tmp1 ? tmp1[0] : NULL;
1183   PetscFunctionReturn(0);
1184 }
1185 
1186 /*@C
1187   PetscDSSetResidual - Set the pointwise residual function for a given test field
1188 
1189   Not collective
1190 
1191   Input Parameters:
1192 + ds - The PetscDS
1193 . f  - The test field number
1194 . f0 - integrand for the test function term
1195 - f1 - integrand for the test function gradient term
1196 
1197   Note: We are using a first order FEM model for the weak form:
1198 
1199   \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)
1200 
1201 The calling sequence for the callbacks f0 and f1 is given by:
1202 
1203 $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1204 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1205 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1206 $    PetscReal t, const PetscReal x[], PetscScalar f0[])
1207 
1208 + dim - the spatial dimension
1209 . Nf - the number of fields
1210 . uOff - the offset into u[] and u_t[] for each field
1211 . uOff_x - the offset into u_x[] for each field
1212 . u - each field evaluated at the current point
1213 . u_t - the time derivative of each field evaluated at the current point
1214 . u_x - the gradient of each field evaluated at the current point
1215 . aOff - the offset into a[] and a_t[] for each auxiliary field
1216 . aOff_x - the offset into a_x[] for each auxiliary field
1217 . a - each auxiliary field evaluated at the current point
1218 . a_t - the time derivative of each auxiliary field evaluated at the current point
1219 . a_x - the gradient of auxiliary each field evaluated at the current point
1220 . t - current time
1221 . x - coordinates of the current point
1222 . numConstants - number of constant parameters
1223 . constants - constant parameters
1224 - f0 - output values at the current point
1225 
1226   Level: intermediate
1227 
1228 .seealso: PetscDSGetResidual()
1229 @*/
1230 PetscErrorCode PetscDSSetResidual(PetscDS ds, PetscInt f,
1231                                   void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1232                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1233                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1234                                              PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
1235                                   void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1236                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1237                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1238                                              PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
1239 {
1240   PetscErrorCode ierr;
1241 
1242   PetscFunctionBegin;
1243   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1244   if (f0) PetscValidFunction(f0, 3);
1245   if (f1) PetscValidFunction(f1, 4);
1246   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1247   ierr = PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1);CHKERRQ(ierr);
1248   PetscFunctionReturn(0);
1249 }
1250 
1251 /*@C
1252   PetscDSHasJacobian - Signals that Jacobian functions have been set
1253 
1254   Not collective
1255 
1256   Input Parameter:
1257 . prob - The PetscDS
1258 
1259   Output Parameter:
1260 . hasJac - flag that pointwise function for the Jacobian has been set
1261 
1262   Level: intermediate
1263 
1264 .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
1265 @*/
1266 PetscErrorCode PetscDSHasJacobian(PetscDS ds, PetscBool *hasJac)
1267 {
1268   PetscErrorCode ierr;
1269 
1270   PetscFunctionBegin;
1271   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1272   ierr = PetscWeakFormHasJacobian(ds->wf, hasJac);CHKERRQ(ierr);
1273   PetscFunctionReturn(0);
1274 }
1275 
1276 /*@C
1277   PetscDSGetJacobian - Get the pointwise Jacobian function for given test and basis field
1278 
1279   Not collective
1280 
1281   Input Parameters:
1282 + ds - The PetscDS
1283 . f  - The test field number
1284 - g  - The field number
1285 
1286   Output Parameters:
1287 + g0 - integrand for the test and basis function term
1288 . g1 - integrand for the test function and basis function gradient term
1289 . g2 - integrand for the test function gradient and basis function term
1290 - g3 - integrand for the test function gradient and basis function gradient term
1291 
1292   Note: We are using a first order FEM model for the weak form:
1293 
1294   \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
1295 
1296 The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
1297 
1298 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1299 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1300 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1301 $    PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])
1302 
1303 + dim - the spatial dimension
1304 . Nf - the number of fields
1305 . uOff - the offset into u[] and u_t[] for each field
1306 . uOff_x - the offset into u_x[] for each field
1307 . u - each field evaluated at the current point
1308 . u_t - the time derivative of each field evaluated at the current point
1309 . u_x - the gradient of each field evaluated at the current point
1310 . aOff - the offset into a[] and a_t[] for each auxiliary field
1311 . aOff_x - the offset into a_x[] for each auxiliary field
1312 . a - each auxiliary field evaluated at the current point
1313 . a_t - the time derivative of each auxiliary field evaluated at the current point
1314 . a_x - the gradient of auxiliary each field evaluated at the current point
1315 . t - current time
1316 . u_tShift - the multiplier a for dF/dU_t
1317 . x - coordinates of the current point
1318 . numConstants - number of constant parameters
1319 . constants - constant parameters
1320 - g0 - output values at the current point
1321 
1322   Level: intermediate
1323 
1324 .seealso: PetscDSSetJacobian()
1325 @*/
1326 PetscErrorCode PetscDSGetJacobian(PetscDS ds, PetscInt f, PetscInt g,
1327                                   void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1328                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1329                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1330                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1331                                   void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1332                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1333                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1334                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1335                                   void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1336                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1337                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1338                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1339                                   void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1340                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1341                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1342                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1343 {
1344   PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
1345   PetscInt       n0, n1, n2, n3;
1346   PetscErrorCode ierr;
1347 
1348   PetscFunctionBegin;
1349   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1350   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
1351   if ((g < 0) || (g >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, ds->Nf);
1352   ierr = PetscWeakFormGetJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);CHKERRQ(ierr);
1353   *g0  = tmp0 ? tmp0[0] : NULL;
1354   *g1  = tmp1 ? tmp1[0] : NULL;
1355   *g2  = tmp2 ? tmp2[0] : NULL;
1356   *g3  = tmp3 ? tmp3[0] : NULL;
1357   PetscFunctionReturn(0);
1358 }
1359 
1360 /*@C
1361   PetscDSSetJacobian - Set the pointwise Jacobian function for given test and basis fields
1362 
1363   Not collective
1364 
1365   Input Parameters:
1366 + ds - The PetscDS
1367 . f  - The test field number
1368 . g  - The field number
1369 . g0 - integrand for the test and basis function term
1370 . g1 - integrand for the test function and basis function gradient term
1371 . g2 - integrand for the test function gradient and basis function term
1372 - g3 - integrand for the test function gradient and basis function gradient term
1373 
1374   Note: We are using a first order FEM model for the weak form:
1375 
1376   \int_\Omega \phi g_0(u, u_t, \nabla u, x, t) \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \nabla \psi
1377 
1378 The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
1379 
1380 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1381 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1382 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1383 $    PetscReal t, const PetscReal x[], PetscScalar g0[])
1384 
1385 + dim - the spatial dimension
1386 . Nf - the number of fields
1387 . uOff - the offset into u[] and u_t[] for each field
1388 . uOff_x - the offset into u_x[] for each field
1389 . u - each field evaluated at the current point
1390 . u_t - the time derivative of each field evaluated at the current point
1391 . u_x - the gradient of each field evaluated at the current point
1392 . aOff - the offset into a[] and a_t[] for each auxiliary field
1393 . aOff_x - the offset into a_x[] for each auxiliary field
1394 . a - each auxiliary field evaluated at the current point
1395 . a_t - the time derivative of each auxiliary field evaluated at the current point
1396 . a_x - the gradient of auxiliary each field evaluated at the current point
1397 . t - current time
1398 . u_tShift - the multiplier a for dF/dU_t
1399 . x - coordinates of the current point
1400 . numConstants - number of constant parameters
1401 . constants - constant parameters
1402 - g0 - output values at the current point
1403 
1404   Level: intermediate
1405 
1406 .seealso: PetscDSGetJacobian()
1407 @*/
1408 PetscErrorCode PetscDSSetJacobian(PetscDS ds, PetscInt f, PetscInt g,
1409                                   void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1410                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1411                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1412                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1413                                   void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1414                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1415                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1416                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1417                                   void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1418                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1419                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1420                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1421                                   void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1422                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1423                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1424                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1425 {
1426   PetscErrorCode ierr;
1427 
1428   PetscFunctionBegin;
1429   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1430   if (g0) PetscValidFunction(g0, 4);
1431   if (g1) PetscValidFunction(g1, 5);
1432   if (g2) PetscValidFunction(g2, 6);
1433   if (g3) PetscValidFunction(g3, 7);
1434   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1435   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
1436   ierr = PetscWeakFormSetIndexJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);CHKERRQ(ierr);
1437   PetscFunctionReturn(0);
1438 }
1439 
1440 /*@C
1441   PetscDSUseJacobianPreconditioner - Whether to construct a Jacobian preconditioner
1442 
1443   Not collective
1444 
1445   Input Parameters:
1446 + prob - The PetscDS
1447 - useJacPre - flag that enables construction of a Jacobian preconditioner
1448 
1449   Level: intermediate
1450 
1451 .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
1452 @*/
1453 PetscErrorCode PetscDSUseJacobianPreconditioner(PetscDS prob, PetscBool useJacPre)
1454 {
1455   PetscFunctionBegin;
1456   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
1457   prob->useJacPre = useJacPre;
1458   PetscFunctionReturn(0);
1459 }
1460 
1461 /*@C
1462   PetscDSHasJacobianPreconditioner - Signals that a Jacobian preconditioner matrix has been set
1463 
1464   Not collective
1465 
1466   Input Parameter:
1467 . prob - The PetscDS
1468 
1469   Output Parameter:
1470 . hasJacPre - flag that pointwise function for Jacobian preconditioner matrix has been set
1471 
1472   Level: intermediate
1473 
1474 .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
1475 @*/
1476 PetscErrorCode PetscDSHasJacobianPreconditioner(PetscDS ds, PetscBool *hasJacPre)
1477 {
1478   PetscErrorCode ierr;
1479 
1480   PetscFunctionBegin;
1481   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1482   *hasJacPre = PETSC_FALSE;
1483   if (!ds->useJacPre) PetscFunctionReturn(0);
1484   ierr = PetscWeakFormHasJacobianPreconditioner(ds->wf, hasJacPre);CHKERRQ(ierr);
1485   PetscFunctionReturn(0);
1486 }
1487 
1488 /*@C
1489   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.
1490 
1491   Not collective
1492 
1493   Input Parameters:
1494 + ds - The PetscDS
1495 . f  - The test field number
1496 - g  - The field number
1497 
1498   Output Parameters:
1499 + g0 - integrand for the test and basis function term
1500 . g1 - integrand for the test function and basis function gradient term
1501 . g2 - integrand for the test function gradient and basis function term
1502 - g3 - integrand for the test function gradient and basis function gradient term
1503 
1504   Note: We are using a first order FEM model for the weak form:
1505 
1506   \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
1507 
1508 The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
1509 
1510 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1511 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1512 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1513 $    PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])
1514 
1515 + dim - the spatial dimension
1516 . Nf - the number of fields
1517 . uOff - the offset into u[] and u_t[] for each field
1518 . uOff_x - the offset into u_x[] for each field
1519 . u - each field evaluated at the current point
1520 . u_t - the time derivative of each field evaluated at the current point
1521 . u_x - the gradient of each field evaluated at the current point
1522 . aOff - the offset into a[] and a_t[] for each auxiliary field
1523 . aOff_x - the offset into a_x[] for each auxiliary field
1524 . a - each auxiliary field evaluated at the current point
1525 . a_t - the time derivative of each auxiliary field evaluated at the current point
1526 . a_x - the gradient of auxiliary each field evaluated at the current point
1527 . t - current time
1528 . u_tShift - the multiplier a for dF/dU_t
1529 . x - coordinates of the current point
1530 . numConstants - number of constant parameters
1531 . constants - constant parameters
1532 - g0 - output values at the current point
1533 
1534   Level: intermediate
1535 
1536 .seealso: PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
1537 @*/
1538 PetscErrorCode PetscDSGetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g,
1539                                   void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1540                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1541                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1542                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1543                                   void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1544                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1545                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1546                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1547                                   void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1548                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1549                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1550                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1551                                   void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1552                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1553                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1554                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1555 {
1556   PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
1557   PetscInt       n0, n1, n2, n3;
1558   PetscErrorCode ierr;
1559 
1560   PetscFunctionBegin;
1561   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1562   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
1563   if ((g < 0) || (g >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, ds->Nf);
1564   ierr = PetscWeakFormGetJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);CHKERRQ(ierr);
1565   *g0  = tmp0 ? tmp0[0] : NULL;
1566   *g1  = tmp1 ? tmp1[0] : NULL;
1567   *g2  = tmp2 ? tmp2[0] : NULL;
1568   *g3  = tmp3 ? tmp3[0] : NULL;
1569   PetscFunctionReturn(0);
1570 }
1571 
1572 /*@C
1573   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.
1574 
1575   Not collective
1576 
1577   Input Parameters:
1578 + ds - The PetscDS
1579 . f  - The test field number
1580 . g  - The field number
1581 . g0 - integrand for the test and basis function term
1582 . g1 - integrand for the test function and basis function gradient term
1583 . g2 - integrand for the test function gradient and basis function term
1584 - g3 - integrand for the test function gradient and basis function gradient term
1585 
1586   Note: We are using a first order FEM model for the weak form:
1587 
1588   \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
1589 
1590 The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
1591 
1592 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1593 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1594 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1595 $    PetscReal t, const PetscReal x[], PetscScalar g0[])
1596 
1597 + dim - the spatial dimension
1598 . Nf - the number of fields
1599 . uOff - the offset into u[] and u_t[] for each field
1600 . uOff_x - the offset into u_x[] for each field
1601 . u - each field evaluated at the current point
1602 . u_t - the time derivative of each field evaluated at the current point
1603 . u_x - the gradient of each field evaluated at the current point
1604 . aOff - the offset into a[] and a_t[] for each auxiliary field
1605 . aOff_x - the offset into a_x[] for each auxiliary field
1606 . a - each auxiliary field evaluated at the current point
1607 . a_t - the time derivative of each auxiliary field evaluated at the current point
1608 . a_x - the gradient of auxiliary each field evaluated at the current point
1609 . t - current time
1610 . u_tShift - the multiplier a for dF/dU_t
1611 . x - coordinates of the current point
1612 . numConstants - number of constant parameters
1613 . constants - constant parameters
1614 - g0 - output values at the current point
1615 
1616   Level: intermediate
1617 
1618 .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobian()
1619 @*/
1620 PetscErrorCode PetscDSSetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g,
1621                                   void (*g0)(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[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1625                                   void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1626                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1627                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1628                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1629                                   void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1630                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1631                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1632                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1633                                   void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1634                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1635                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1636                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1637 {
1638   PetscErrorCode ierr;
1639 
1640   PetscFunctionBegin;
1641   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1642   if (g0) PetscValidFunction(g0, 4);
1643   if (g1) PetscValidFunction(g1, 5);
1644   if (g2) PetscValidFunction(g2, 6);
1645   if (g3) PetscValidFunction(g3, 7);
1646   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1647   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
1648   ierr = PetscWeakFormSetIndexJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);CHKERRQ(ierr);
1649   PetscFunctionReturn(0);
1650 }
1651 
1652 /*@C
1653   PetscDSHasDynamicJacobian - Signals that a dynamic Jacobian, dF/du_t, has been set
1654 
1655   Not collective
1656 
1657   Input Parameter:
1658 . ds - The PetscDS
1659 
1660   Output Parameter:
1661 . hasDynJac - flag that pointwise function for dynamic Jacobian has been set
1662 
1663   Level: intermediate
1664 
1665 .seealso: PetscDSGetDynamicJacobian(), PetscDSSetDynamicJacobian(), PetscDSGetJacobian()
1666 @*/
1667 PetscErrorCode PetscDSHasDynamicJacobian(PetscDS ds, PetscBool *hasDynJac)
1668 {
1669   PetscErrorCode ierr;
1670 
1671   PetscFunctionBegin;
1672   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1673   ierr = PetscWeakFormHasDynamicJacobian(ds->wf, hasDynJac);CHKERRQ(ierr);
1674   PetscFunctionReturn(0);
1675 }
1676 
1677 /*@C
1678   PetscDSGetDynamicJacobian - Get the pointwise dynamic Jacobian, dF/du_t, function for given test and basis field
1679 
1680   Not collective
1681 
1682   Input Parameters:
1683 + ds - The PetscDS
1684 . f  - The test field number
1685 - g  - The field number
1686 
1687   Output Parameters:
1688 + g0 - integrand for the test and basis function term
1689 . g1 - integrand for the test function and basis function gradient term
1690 . g2 - integrand for the test function gradient and basis function term
1691 - g3 - integrand for the test function gradient and basis function gradient term
1692 
1693   Note: We are using a first order FEM model for the weak form:
1694 
1695   \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
1696 
1697 The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
1698 
1699 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1700 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1701 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1702 $    PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])
1703 
1704 + dim - the spatial dimension
1705 . Nf - the number of fields
1706 . uOff - the offset into u[] and u_t[] for each field
1707 . uOff_x - the offset into u_x[] for each field
1708 . u - each field evaluated at the current point
1709 . u_t - the time derivative of each field evaluated at the current point
1710 . u_x - the gradient of each field evaluated at the current point
1711 . aOff - the offset into a[] and a_t[] for each auxiliary field
1712 . aOff_x - the offset into a_x[] for each auxiliary field
1713 . a - each auxiliary field evaluated at the current point
1714 . a_t - the time derivative of each auxiliary field evaluated at the current point
1715 . a_x - the gradient of auxiliary each field evaluated at the current point
1716 . t - current time
1717 . u_tShift - the multiplier a for dF/dU_t
1718 . x - coordinates of the current point
1719 . numConstants - number of constant parameters
1720 . constants - constant parameters
1721 - g0 - output values at the current point
1722 
1723   Level: intermediate
1724 
1725 .seealso: PetscDSSetJacobian()
1726 @*/
1727 PetscErrorCode PetscDSGetDynamicJacobian(PetscDS ds, PetscInt f, PetscInt g,
1728                                          void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1729                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1730                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1731                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1732                                          void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1733                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1734                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1735                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1736                                          void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1737                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1738                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1739                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1740                                          void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1741                                                      const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1742                                                      const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1743                                                      PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1744 {
1745   PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
1746   PetscInt       n0, n1, n2, n3;
1747   PetscErrorCode ierr;
1748 
1749   PetscFunctionBegin;
1750   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1751   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
1752   if ((g < 0) || (g >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, ds->Nf);
1753   ierr = PetscWeakFormGetDynamicJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);CHKERRQ(ierr);
1754   *g0  = tmp0 ? tmp0[0] : NULL;
1755   *g1  = tmp1 ? tmp1[0] : NULL;
1756   *g2  = tmp2 ? tmp2[0] : NULL;
1757   *g3  = tmp3 ? tmp3[0] : NULL;
1758   PetscFunctionReturn(0);
1759 }
1760 
1761 /*@C
1762   PetscDSSetDynamicJacobian - Set the pointwise dynamic Jacobian, dF/du_t, function for given test and basis fields
1763 
1764   Not collective
1765 
1766   Input Parameters:
1767 + ds - The PetscDS
1768 . f  - The test field number
1769 . g  - The field number
1770 . g0 - integrand for the test and basis function term
1771 . g1 - integrand for the test function and basis function gradient term
1772 . g2 - integrand for the test function gradient and basis function term
1773 - g3 - integrand for the test function gradient and basis function gradient term
1774 
1775   Note: We are using a first order FEM model for the weak form:
1776 
1777   \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
1778 
1779 The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
1780 
1781 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1782 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1783 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1784 $    PetscReal t, const PetscReal x[], PetscScalar g0[])
1785 
1786 + dim - the spatial dimension
1787 . Nf - the number of fields
1788 . uOff - the offset into u[] and u_t[] for each field
1789 . uOff_x - the offset into u_x[] for each field
1790 . u - each field evaluated at the current point
1791 . u_t - the time derivative of each field evaluated at the current point
1792 . u_x - the gradient of each field evaluated at the current point
1793 . aOff - the offset into a[] and a_t[] for each auxiliary field
1794 . aOff_x - the offset into a_x[] for each auxiliary field
1795 . a - each auxiliary field evaluated at the current point
1796 . a_t - the time derivative of each auxiliary field evaluated at the current point
1797 . a_x - the gradient of auxiliary each field evaluated at the current point
1798 . t - current time
1799 . u_tShift - the multiplier a for dF/dU_t
1800 . x - coordinates of the current point
1801 . numConstants - number of constant parameters
1802 . constants - constant parameters
1803 - g0 - output values at the current point
1804 
1805   Level: intermediate
1806 
1807 .seealso: PetscDSGetJacobian()
1808 @*/
1809 PetscErrorCode PetscDSSetDynamicJacobian(PetscDS ds, PetscInt f, PetscInt g,
1810                                          void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1811                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1812                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1813                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1814                                          void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1815                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1816                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1817                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1818                                          void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1819                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1820                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1821                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1822                                          void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1823                                                     const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1824                                                     const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1825                                                     PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1826 {
1827   PetscErrorCode ierr;
1828 
1829   PetscFunctionBegin;
1830   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1831   if (g0) PetscValidFunction(g0, 4);
1832   if (g1) PetscValidFunction(g1, 5);
1833   if (g2) PetscValidFunction(g2, 6);
1834   if (g3) PetscValidFunction(g3, 7);
1835   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1836   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
1837   ierr = PetscWeakFormSetIndexDynamicJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);CHKERRQ(ierr);
1838   PetscFunctionReturn(0);
1839 }
1840 
1841 /*@C
1842   PetscDSGetRiemannSolver - Returns the Riemann solver for the given field
1843 
1844   Not collective
1845 
1846   Input Arguments:
1847 + ds - The PetscDS object
1848 - f  - The field number
1849 
1850   Output Argument:
1851 . r    - Riemann solver
1852 
1853   Calling sequence for r:
1854 
1855 $ r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx)
1856 
1857 + dim  - The spatial dimension
1858 . Nf   - The number of fields
1859 . x    - The coordinates at a point on the interface
1860 . n    - The normal vector to the interface
1861 . uL   - The state vector to the left of the interface
1862 . uR   - The state vector to the right of the interface
1863 . flux - output array of flux through the interface
1864 . numConstants - number of constant parameters
1865 . constants - constant parameters
1866 - ctx  - optional user context
1867 
1868   Level: intermediate
1869 
1870 .seealso: PetscDSSetRiemannSolver()
1871 @*/
1872 PetscErrorCode PetscDSGetRiemannSolver(PetscDS ds, PetscInt f,
1873                                        void (**r)(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscInt numConstants, const PetscScalar constants[], PetscScalar flux[], void *ctx))
1874 {
1875   PetscRiemannFunc *tmp;
1876   PetscInt          n;
1877   PetscErrorCode    ierr;
1878 
1879   PetscFunctionBegin;
1880   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1881   PetscValidPointer(r, 3);
1882   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
1883   ierr = PetscWeakFormGetRiemannSolver(ds->wf, NULL, 0, f, 0, &n, &tmp);CHKERRQ(ierr);
1884   *r   = tmp ? tmp[0] : NULL;
1885   PetscFunctionReturn(0);
1886 }
1887 
1888 /*@C
1889   PetscDSSetRiemannSolver - Sets the Riemann solver for the given field
1890 
1891   Not collective
1892 
1893   Input Arguments:
1894 + ds - The PetscDS object
1895 . f  - The field number
1896 - r  - Riemann solver
1897 
1898   Calling sequence for r:
1899 
1900 $ r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx)
1901 
1902 + dim  - The spatial dimension
1903 . Nf   - The number of fields
1904 . x    - The coordinates at a point on the interface
1905 . n    - The normal vector to the interface
1906 . uL   - The state vector to the left of the interface
1907 . uR   - The state vector to the right of the interface
1908 . flux - output array of flux through the interface
1909 . numConstants - number of constant parameters
1910 . constants - constant parameters
1911 - ctx  - optional user context
1912 
1913   Level: intermediate
1914 
1915 .seealso: PetscDSGetRiemannSolver()
1916 @*/
1917 PetscErrorCode PetscDSSetRiemannSolver(PetscDS ds, PetscInt f,
1918                                        void (*r)(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscInt numConstants, const PetscScalar constants[], PetscScalar flux[], void *ctx))
1919 {
1920   PetscErrorCode ierr;
1921 
1922   PetscFunctionBegin;
1923   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1924   if (r) PetscValidFunction(r, 3);
1925   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1926   ierr = PetscWeakFormSetIndexRiemannSolver(ds->wf, NULL, 0, f, 0, 0, r);CHKERRQ(ierr);
1927   PetscFunctionReturn(0);
1928 }
1929 
1930 /*@C
1931   PetscDSGetUpdate - Get the pointwise update function for a given field
1932 
1933   Not collective
1934 
1935   Input Parameters:
1936 + ds - The PetscDS
1937 - f  - The field number
1938 
1939   Output Parameters:
1940 . update - update function
1941 
1942   Note: The calling sequence for the callback update is given by:
1943 
1944 $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1945 $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1946 $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1947 $        PetscReal t, const PetscReal x[], PetscScalar uNew[])
1948 
1949 + dim - the spatial dimension
1950 . Nf - the number of fields
1951 . uOff - the offset into u[] and u_t[] for each field
1952 . uOff_x - the offset into u_x[] for each field
1953 . u - each field evaluated at the current point
1954 . u_t - the time derivative of each field evaluated at the current point
1955 . u_x - the gradient of each field evaluated at the current point
1956 . aOff - the offset into a[] and a_t[] for each auxiliary field
1957 . aOff_x - the offset into a_x[] for each auxiliary field
1958 . a - each auxiliary field evaluated at the current point
1959 . a_t - the time derivative of each auxiliary field evaluated at the current point
1960 . a_x - the gradient of auxiliary each field evaluated at the current point
1961 . t - current time
1962 . x - coordinates of the current point
1963 - uNew - new value for field at the current point
1964 
1965   Level: intermediate
1966 
1967 .seealso: PetscDSSetUpdate(), PetscDSSetResidual()
1968 @*/
1969 PetscErrorCode PetscDSGetUpdate(PetscDS ds, PetscInt f,
1970                                   void (**update)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1971                                                   const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1972                                                   const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1973                                                   PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[]))
1974 {
1975   PetscFunctionBegin;
1976   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
1977   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
1978   if (update) {PetscValidPointer(update, 3); *update = ds->update[f];}
1979   PetscFunctionReturn(0);
1980 }
1981 
1982 /*@C
1983   PetscDSSetUpdate - Set the pointwise update function for a given field
1984 
1985   Not collective
1986 
1987   Input Parameters:
1988 + ds     - The PetscDS
1989 . f      - The field number
1990 - update - update function
1991 
1992   Note: The calling sequence for the callback update is given by:
1993 
1994 $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1995 $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1996 $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1997 $        PetscReal t, const PetscReal x[], PetscScalar uNew[])
1998 
1999 + dim - the spatial dimension
2000 . Nf - the number of fields
2001 . uOff - the offset into u[] and u_t[] for each field
2002 . uOff_x - the offset into u_x[] for each field
2003 . u - each field evaluated at the current point
2004 . u_t - the time derivative of each field evaluated at the current point
2005 . u_x - the gradient of each field evaluated at the current point
2006 . aOff - the offset into a[] and a_t[] for each auxiliary field
2007 . aOff_x - the offset into a_x[] for each auxiliary field
2008 . a - each auxiliary field evaluated at the current point
2009 . a_t - the time derivative of each auxiliary field evaluated at the current point
2010 . a_x - the gradient of auxiliary each field evaluated at the current point
2011 . t - current time
2012 . x - coordinates of the current point
2013 - uNew - new field values at the current point
2014 
2015   Level: intermediate
2016 
2017 .seealso: PetscDSGetResidual()
2018 @*/
2019 PetscErrorCode PetscDSSetUpdate(PetscDS ds, PetscInt f,
2020                                 void (*update)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2021                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2022                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2023                                                PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[]))
2024 {
2025   PetscErrorCode ierr;
2026 
2027   PetscFunctionBegin;
2028   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
2029   if (update) PetscValidFunction(update, 3);
2030   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
2031   ierr = PetscDSEnlarge_Static(ds, f+1);CHKERRQ(ierr);
2032   ds->update[f] = update;
2033   PetscFunctionReturn(0);
2034 }
2035 
2036 PetscErrorCode PetscDSGetContext(PetscDS ds, PetscInt f, void **ctx)
2037 {
2038   PetscFunctionBegin;
2039   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
2040   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
2041   PetscValidPointer(ctx, 3);
2042   *ctx = ds->ctx[f];
2043   PetscFunctionReturn(0);
2044 }
2045 
2046 PetscErrorCode PetscDSSetContext(PetscDS ds, PetscInt f, void *ctx)
2047 {
2048   PetscErrorCode ierr;
2049 
2050   PetscFunctionBegin;
2051   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
2052   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
2053   ierr = PetscDSEnlarge_Static(ds, f+1);CHKERRQ(ierr);
2054   ds->ctx[f] = ctx;
2055   PetscFunctionReturn(0);
2056 }
2057 
2058 /*@C
2059   PetscDSGetBdResidual - Get the pointwise boundary residual function for a given test field
2060 
2061   Not collective
2062 
2063   Input Parameters:
2064 + ds - The PetscDS
2065 - f  - The test field number
2066 
2067   Output Parameters:
2068 + f0 - boundary integrand for the test function term
2069 - f1 - boundary integrand for the test function gradient term
2070 
2071   Note: We are using a first order FEM model for the weak form:
2072 
2073   \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
2074 
2075 The calling sequence for the callbacks f0 and f1 is given by:
2076 
2077 $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2078 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2079 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2080 $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])
2081 
2082 + dim - the spatial dimension
2083 . Nf - the number of fields
2084 . uOff - the offset into u[] and u_t[] for each field
2085 . uOff_x - the offset into u_x[] for each field
2086 . u - each field evaluated at the current point
2087 . u_t - the time derivative of each field evaluated at the current point
2088 . u_x - the gradient of each field evaluated at the current point
2089 . aOff - the offset into a[] and a_t[] for each auxiliary field
2090 . aOff_x - the offset into a_x[] for each auxiliary field
2091 . a - each auxiliary field evaluated at the current point
2092 . a_t - the time derivative of each auxiliary field evaluated at the current point
2093 . a_x - the gradient of auxiliary each field evaluated at the current point
2094 . t - current time
2095 . x - coordinates of the current point
2096 . n - unit normal at the current point
2097 . numConstants - number of constant parameters
2098 . constants - constant parameters
2099 - f0 - output values at the current point
2100 
2101   Level: intermediate
2102 
2103 .seealso: PetscDSSetBdResidual()
2104 @*/
2105 PetscErrorCode PetscDSGetBdResidual(PetscDS ds, PetscInt f,
2106                                     void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2107                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2108                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2109                                                 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
2110                                     void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2111                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2112                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2113                                                 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
2114 {
2115   PetscBdPointFunc *tmp0, *tmp1;
2116   PetscInt          n0, n1;
2117   PetscErrorCode    ierr;
2118 
2119   PetscFunctionBegin;
2120   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
2121   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
2122   ierr = PetscWeakFormGetBdResidual(ds->wf, NULL, 0, f, 0, &n0, &tmp0, &n1, &tmp1);CHKERRQ(ierr);
2123   *f0  = tmp0 ? tmp0[0] : NULL;
2124   *f1  = tmp1 ? tmp1[0] : NULL;
2125   PetscFunctionReturn(0);
2126 }
2127 
2128 /*@C
2129   PetscDSSetBdResidual - Get the pointwise boundary residual function for a given test field
2130 
2131   Not collective
2132 
2133   Input Parameters:
2134 + ds - The PetscDS
2135 . f  - The test field number
2136 . f0 - boundary integrand for the test function term
2137 - f1 - boundary integrand for the test function gradient term
2138 
2139   Note: We are using a first order FEM model for the weak form:
2140 
2141   \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
2142 
2143 The calling sequence for the callbacks f0 and f1 is given by:
2144 
2145 $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2146 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2147 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2148 $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])
2149 
2150 + dim - the spatial dimension
2151 . Nf - the number of fields
2152 . uOff - the offset into u[] and u_t[] for each field
2153 . uOff_x - the offset into u_x[] for each field
2154 . u - each field evaluated at the current point
2155 . u_t - the time derivative of each field evaluated at the current point
2156 . u_x - the gradient of each field evaluated at the current point
2157 . aOff - the offset into a[] and a_t[] for each auxiliary field
2158 . aOff_x - the offset into a_x[] for each auxiliary field
2159 . a - each auxiliary field evaluated at the current point
2160 . a_t - the time derivative of each auxiliary field evaluated at the current point
2161 . a_x - the gradient of auxiliary each field evaluated at the current point
2162 . t - current time
2163 . x - coordinates of the current point
2164 . n - unit normal at the current point
2165 . numConstants - number of constant parameters
2166 . constants - constant parameters
2167 - f0 - output values at the current point
2168 
2169   Level: intermediate
2170 
2171 .seealso: PetscDSGetBdResidual()
2172 @*/
2173 PetscErrorCode PetscDSSetBdResidual(PetscDS ds, PetscInt f,
2174                                     void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2175                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2176                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2177                                                PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
2178                                     void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2179                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2180                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2181                                                PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
2182 {
2183   PetscErrorCode ierr;
2184 
2185   PetscFunctionBegin;
2186   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
2187   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
2188   ierr = PetscWeakFormSetIndexBdResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1);CHKERRQ(ierr);
2189   PetscFunctionReturn(0);
2190 }
2191 
2192 /*@
2193   PetscDSHasBdJacobian - Signals that boundary Jacobian functions have been set
2194 
2195   Not collective
2196 
2197   Input Parameter:
2198 . ds - The PetscDS
2199 
2200   Output Parameter:
2201 . hasBdJac - flag that pointwise function for the boundary Jacobian has been set
2202 
2203   Level: intermediate
2204 
2205 .seealso: PetscDSHasJacobian(), PetscDSSetBdJacobian(), PetscDSGetBdJacobian()
2206 @*/
2207 PetscErrorCode PetscDSHasBdJacobian(PetscDS ds, PetscBool *hasBdJac)
2208 {
2209   PetscErrorCode ierr;
2210 
2211   PetscFunctionBegin;
2212   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
2213   PetscValidBoolPointer(hasBdJac, 2);
2214   ierr = PetscWeakFormHasBdJacobian(ds->wf, hasBdJac);CHKERRQ(ierr);
2215   PetscFunctionReturn(0);
2216 }
2217 
2218 /*@C
2219   PetscDSGetBdJacobian - Get the pointwise boundary Jacobian function for given test and basis field
2220 
2221   Not collective
2222 
2223   Input Parameters:
2224 + ds - The PetscDS
2225 . f  - The test field number
2226 - g  - The field number
2227 
2228   Output Parameters:
2229 + g0 - integrand for the test and basis function term
2230 . g1 - integrand for the test function and basis function gradient term
2231 . g2 - integrand for the test function gradient and basis function term
2232 - g3 - integrand for the test function gradient and basis function gradient term
2233 
2234   Note: We are using a first order FEM model for the weak form:
2235 
2236   \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
2237 
2238 The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
2239 
2240 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2241 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2242 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2243 $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[])
2244 
2245 + dim - the spatial dimension
2246 . Nf - the number of fields
2247 . uOff - the offset into u[] and u_t[] for each field
2248 . uOff_x - the offset into u_x[] for each field
2249 . u - each field evaluated at the current point
2250 . u_t - the time derivative of each field evaluated at the current point
2251 . u_x - the gradient of each field evaluated at the current point
2252 . aOff - the offset into a[] and a_t[] for each auxiliary field
2253 . aOff_x - the offset into a_x[] for each auxiliary field
2254 . a - each auxiliary field evaluated at the current point
2255 . a_t - the time derivative of each auxiliary field evaluated at the current point
2256 . a_x - the gradient of auxiliary each field evaluated at the current point
2257 . t - current time
2258 . u_tShift - the multiplier a for dF/dU_t
2259 . x - coordinates of the current point
2260 . n - normal at the current point
2261 . numConstants - number of constant parameters
2262 . constants - constant parameters
2263 - g0 - output values at the current point
2264 
2265   Level: intermediate
2266 
2267 .seealso: PetscDSSetBdJacobian()
2268 @*/
2269 PetscErrorCode PetscDSGetBdJacobian(PetscDS ds, PetscInt f, PetscInt g,
2270                                     void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2271                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2272                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2273                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
2274                                     void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2275                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2276                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2277                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
2278                                     void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2279                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2280                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2281                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
2282                                     void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2283                                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2284                                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2285                                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2286 {
2287   PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3;
2288   PetscInt         n0, n1, n2, n3;
2289   PetscErrorCode   ierr;
2290 
2291   PetscFunctionBegin;
2292   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
2293   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
2294   if ((g < 0) || (g >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, ds->Nf);
2295   ierr = PetscWeakFormGetBdJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);CHKERRQ(ierr);
2296   *g0  = tmp0 ? tmp0[0] : NULL;
2297   *g1  = tmp1 ? tmp1[0] : NULL;
2298   *g2  = tmp2 ? tmp2[0] : NULL;
2299   *g3  = tmp3 ? tmp3[0] : NULL;
2300   PetscFunctionReturn(0);
2301 }
2302 
2303 /*@C
2304   PetscDSSetBdJacobian - Set the pointwise boundary Jacobian function for given test and basis field
2305 
2306   Not collective
2307 
2308   Input Parameters:
2309 + ds - The PetscDS
2310 . f  - The test field number
2311 . g  - The field number
2312 . g0 - integrand for the test and basis function term
2313 . g1 - integrand for the test function and basis function gradient term
2314 . g2 - integrand for the test function gradient and basis function term
2315 - g3 - integrand for the test function gradient and basis function gradient term
2316 
2317   Note: We are using a first order FEM model for the weak form:
2318 
2319   \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
2320 
2321 The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
2322 
2323 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2324 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2325 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2326 $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[])
2327 
2328 + dim - the spatial dimension
2329 . Nf - the number of fields
2330 . uOff - the offset into u[] and u_t[] for each field
2331 . uOff_x - the offset into u_x[] for each field
2332 . u - each field evaluated at the current point
2333 . u_t - the time derivative of each field evaluated at the current point
2334 . u_x - the gradient of each field evaluated at the current point
2335 . aOff - the offset into a[] and a_t[] for each auxiliary field
2336 . aOff_x - the offset into a_x[] for each auxiliary field
2337 . a - each auxiliary field evaluated at the current point
2338 . a_t - the time derivative of each auxiliary field evaluated at the current point
2339 . a_x - the gradient of auxiliary each field evaluated at the current point
2340 . t - current time
2341 . u_tShift - the multiplier a for dF/dU_t
2342 . x - coordinates of the current point
2343 . n - normal at the current point
2344 . numConstants - number of constant parameters
2345 . constants - constant parameters
2346 - g0 - output values at the current point
2347 
2348   Level: intermediate
2349 
2350 .seealso: PetscDSGetBdJacobian()
2351 @*/
2352 PetscErrorCode PetscDSSetBdJacobian(PetscDS ds, PetscInt f, PetscInt g,
2353                                     void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2354                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2355                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2356                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
2357                                     void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2358                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2359                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2360                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
2361                                     void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2362                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2363                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2364                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
2365                                     void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2366                                                const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2367                                                const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2368                                                PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2369 {
2370   PetscErrorCode ierr;
2371 
2372   PetscFunctionBegin;
2373   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
2374   if (g0) PetscValidFunction(g0, 4);
2375   if (g1) PetscValidFunction(g1, 5);
2376   if (g2) PetscValidFunction(g2, 6);
2377   if (g3) PetscValidFunction(g3, 7);
2378   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
2379   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
2380   ierr = PetscWeakFormSetIndexBdJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);CHKERRQ(ierr);
2381   PetscFunctionReturn(0);
2382 }
2383 
2384 /*@
2385   PetscDSHasBdJacobianPreconditioner - Signals that boundary Jacobian preconditioner functions have been set
2386 
2387   Not collective
2388 
2389   Input Parameter:
2390 . ds - The PetscDS
2391 
2392   Output Parameter:
2393 . hasBdJac - flag that pointwise function for the boundary Jacobian preconditioner has been set
2394 
2395   Level: intermediate
2396 
2397 .seealso: PetscDSHasJacobian(), PetscDSSetBdJacobian(), PetscDSGetBdJacobian()
2398 @*/
2399 PetscErrorCode PetscDSHasBdJacobianPreconditioner(PetscDS ds, PetscBool *hasBdJacPre)
2400 {
2401   PetscErrorCode ierr;
2402 
2403   PetscFunctionBegin;
2404   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
2405   PetscValidBoolPointer(hasBdJacPre, 2);
2406   ierr = PetscWeakFormHasBdJacobianPreconditioner(ds->wf, hasBdJacPre);CHKERRQ(ierr);
2407   PetscFunctionReturn(0);
2408 }
2409 
2410 /*@C
2411   PetscDSGetBdJacobianPreconditioner - Get the pointwise boundary Jacobian preconditioner function for given test and basis field
2412 
2413   Not collective
2414 
2415   Input Parameters:
2416 + ds - The PetscDS
2417 . f  - The test field number
2418 - g  - The field number
2419 
2420   Output Parameters:
2421 + g0 - integrand for the test and basis function term
2422 . g1 - integrand for the test function and basis function gradient term
2423 . g2 - integrand for the test function gradient and basis function term
2424 - g3 - integrand for the test function gradient and basis function gradient term
2425 
2426   Note: We are using a first order FEM model for the weak form:
2427 
2428   \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
2429 
2430 The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
2431 
2432 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2433 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2434 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2435 $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
2436 
2437 + dim - the spatial dimension
2438 . Nf - the number of fields
2439 . NfAux - the number of auxiliary fields
2440 . uOff - the offset into u[] and u_t[] for each field
2441 . uOff_x - the offset into u_x[] for each field
2442 . u - each field evaluated at the current point
2443 . u_t - the time derivative of each field evaluated at the current point
2444 . u_x - the gradient of each field evaluated at the current point
2445 . aOff - the offset into a[] and a_t[] for each auxiliary field
2446 . aOff_x - the offset into a_x[] for each auxiliary field
2447 . a - each auxiliary field evaluated at the current point
2448 . a_t - the time derivative of each auxiliary field evaluated at the current point
2449 . a_x - the gradient of auxiliary each field evaluated at the current point
2450 . t - current time
2451 . u_tShift - the multiplier a for dF/dU_t
2452 . x - coordinates of the current point
2453 . n - normal at the current point
2454 . numConstants - number of constant parameters
2455 . constants - constant parameters
2456 - g0 - output values at the current point
2457 
2458   This is not yet available in Fortran.
2459 
2460   Level: intermediate
2461 
2462 .seealso: PetscDSSetBdJacobianPreconditioner()
2463 @*/
2464 PetscErrorCode PetscDSGetBdJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g,
2465                                                   void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2466                                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2467                                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2468                                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
2469                                                   void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2470                                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2471                                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2472                                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
2473                                                   void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2474                                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2475                                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2476                                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
2477                                                   void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2478                                                               const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2479                                                               const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2480                                                               PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2481 {
2482   PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3;
2483   PetscInt         n0, n1, n2, n3;
2484   PetscErrorCode   ierr;
2485 
2486   PetscFunctionBegin;
2487   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
2488   if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf);
2489   if ((g < 0) || (g >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, ds->Nf);
2490   ierr = PetscWeakFormGetBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);CHKERRQ(ierr);
2491   *g0  = tmp0 ? tmp0[0] : NULL;
2492   *g1  = tmp1 ? tmp1[0] : NULL;
2493   *g2  = tmp2 ? tmp2[0] : NULL;
2494   *g3  = tmp3 ? tmp3[0] : NULL;
2495   PetscFunctionReturn(0);
2496 }
2497 
2498 /*@C
2499   PetscDSSetBdJacobianPreconditioner - Set the pointwise boundary Jacobian preconditioner function for given test and basis field
2500 
2501   Not collective
2502 
2503   Input Parameters:
2504 + ds - The PetscDS
2505 . f  - The test field number
2506 . g  - The field number
2507 . g0 - integrand for the test and basis function term
2508 . g1 - integrand for the test function and basis function gradient term
2509 . g2 - integrand for the test function gradient and basis function term
2510 - g3 - integrand for the test function gradient and basis function gradient term
2511 
2512   Note: We are using a first order FEM model for the weak form:
2513 
2514   \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
2515 
2516 The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
2517 
2518 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2519 $    const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2520 $    const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2521 $    PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
2522 
2523 + dim - the spatial dimension
2524 . Nf - the number of fields
2525 . NfAux - the number of auxiliary fields
2526 . uOff - the offset into u[] and u_t[] for each field
2527 . uOff_x - the offset into u_x[] for each field
2528 . u - each field evaluated at the current point
2529 . u_t - the time derivative of each field evaluated at the current point
2530 . u_x - the gradient of each field evaluated at the current point
2531 . aOff - the offset into a[] and a_t[] for each auxiliary field
2532 . aOff_x - the offset into a_x[] for each auxiliary field
2533 . a - each auxiliary field evaluated at the current point
2534 . a_t - the time derivative of each auxiliary field evaluated at the current point
2535 . a_x - the gradient of auxiliary each field evaluated at the current point
2536 . t - current time
2537 . u_tShift - the multiplier a for dF/dU_t
2538 . x - coordinates of the current point
2539 . n - normal at the current point
2540 . numConstants - number of constant parameters
2541 . constants - constant parameters
2542 - g0 - output values at the current point
2543 
2544   This is not yet available in Fortran.
2545 
2546   Level: intermediate
2547 
2548 .seealso: PetscDSGetBdJacobianPreconditioner()
2549 @*/
2550 PetscErrorCode PetscDSSetBdJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g,
2551                                                   void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2552                                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2553                                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2554                                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
2555                                                   void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2556                                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2557                                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2558                                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
2559                                                   void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2560                                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2561                                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2562                                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
2563                                                   void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2564                                                              const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2565                                                              const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2566                                                              PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2567 {
2568   PetscErrorCode ierr;
2569 
2570   PetscFunctionBegin;
2571   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
2572   if (g0) PetscValidFunction(g0, 4);
2573   if (g1) PetscValidFunction(g1, 5);
2574   if (g2) PetscValidFunction(g2, 6);
2575   if (g3) PetscValidFunction(g3, 7);
2576   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
2577   if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
2578   ierr = PetscWeakFormSetIndexBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);CHKERRQ(ierr);
2579   PetscFunctionReturn(0);
2580 }
2581 
2582 /*@C
2583   PetscDSGetExactSolution - Get the pointwise exact solution function for a given test field
2584 
2585   Not collective
2586 
2587   Input Parameters:
2588 + prob - The PetscDS
2589 - f    - The test field number
2590 
2591   Output Parameter:
2592 + exactSol - exact solution for the test field
2593 - exactCtx - exact solution context
2594 
2595   Note: The calling sequence for the solution functions is given by:
2596 
2597 $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2598 
2599 + dim - the spatial dimension
2600 . t - current time
2601 . x - coordinates of the current point
2602 . Nc - the number of field components
2603 . u - the solution field evaluated at the current point
2604 - ctx - a user context
2605 
2606   Level: intermediate
2607 
2608 .seealso: PetscDSSetExactSolution(), PetscDSGetExactSolutionTimeDerivative()
2609 @*/
2610 PetscErrorCode PetscDSGetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx)
2611 {
2612   PetscFunctionBegin;
2613   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2614   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);
2615   if (sol) {PetscValidPointer(sol, 3); *sol = prob->exactSol[f];}
2616   if (ctx) {PetscValidPointer(ctx, 4); *ctx = prob->exactCtx[f];}
2617   PetscFunctionReturn(0);
2618 }
2619 
2620 /*@C
2621   PetscDSSetExactSolution - Set the pointwise exact solution function for a given test field
2622 
2623   Not collective
2624 
2625   Input Parameters:
2626 + prob - The PetscDS
2627 . f    - The test field number
2628 . sol  - solution function for the test fields
2629 - ctx  - solution context or NULL
2630 
2631   Note: The calling sequence for solution functions is given by:
2632 
2633 $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2634 
2635 + dim - the spatial dimension
2636 . t - current time
2637 . x - coordinates of the current point
2638 . Nc - the number of field components
2639 . u - the solution field evaluated at the current point
2640 - ctx - a user context
2641 
2642   Level: intermediate
2643 
2644 .seealso: PetscDSGetExactSolution()
2645 @*/
2646 PetscErrorCode PetscDSSetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx)
2647 {
2648   PetscErrorCode ierr;
2649 
2650   PetscFunctionBegin;
2651   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2652   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
2653   ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr);
2654   if (sol) {PetscValidFunction(sol, 3); prob->exactSol[f] = sol;}
2655   if (ctx) {PetscValidFunction(ctx, 4); prob->exactCtx[f] = ctx;}
2656   PetscFunctionReturn(0);
2657 }
2658 
2659 /*@C
2660   PetscDSGetExactSolutionTimeDerivative - Get the pointwise time derivative of the exact solution function for a given test field
2661 
2662   Not collective
2663 
2664   Input Parameters:
2665 + prob - The PetscDS
2666 - f    - The test field number
2667 
2668   Output Parameter:
2669 + exactSol - time derivative of the exact solution for the test field
2670 - exactCtx - time derivative of the exact solution context
2671 
2672   Note: The calling sequence for the solution functions is given by:
2673 
2674 $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2675 
2676 + dim - the spatial dimension
2677 . t - current time
2678 . x - coordinates of the current point
2679 . Nc - the number of field components
2680 . u - the solution field evaluated at the current point
2681 - ctx - a user context
2682 
2683   Level: intermediate
2684 
2685 .seealso: PetscDSSetExactSolutionTimeDerivative(), PetscDSGetExactSolution()
2686 @*/
2687 PetscErrorCode PetscDSGetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx)
2688 {
2689   PetscFunctionBegin;
2690   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2691   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);
2692   if (sol) {PetscValidPointer(sol, 3); *sol = prob->exactSol_t[f];}
2693   if (ctx) {PetscValidPointer(ctx, 4); *ctx = prob->exactCtx_t[f];}
2694   PetscFunctionReturn(0);
2695 }
2696 
2697 /*@C
2698   PetscDSSetExactSolutionTimeDerivative - Set the pointwise time derivative of the exact solution function for a given test field
2699 
2700   Not collective
2701 
2702   Input Parameters:
2703 + prob - The PetscDS
2704 . f    - The test field number
2705 . sol  - time derivative of the solution function for the test fields
2706 - ctx  - time derivative of the solution context or NULL
2707 
2708   Note: The calling sequence for solution functions is given by:
2709 
2710 $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2711 
2712 + dim - the spatial dimension
2713 . t - current time
2714 . x - coordinates of the current point
2715 . Nc - the number of field components
2716 . u - the solution field evaluated at the current point
2717 - ctx - a user context
2718 
2719   Level: intermediate
2720 
2721 .seealso: PetscDSGetExactSolutionTimeDerivative(), PetscDSSetExactSolution()
2722 @*/
2723 PetscErrorCode PetscDSSetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx)
2724 {
2725   PetscErrorCode ierr;
2726 
2727   PetscFunctionBegin;
2728   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2729   if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
2730   ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr);
2731   if (sol) {PetscValidFunction(sol, 3); prob->exactSol_t[f] = sol;}
2732   if (ctx) {PetscValidFunction(ctx, 4); prob->exactCtx_t[f] = ctx;}
2733   PetscFunctionReturn(0);
2734 }
2735 
2736 /*@C
2737   PetscDSGetConstants - Returns the array of constants passed to point functions
2738 
2739   Not collective
2740 
2741   Input Parameter:
2742 . prob - The PetscDS object
2743 
2744   Output Parameters:
2745 + numConstants - The number of constants
2746 - constants    - The array of constants, NULL if there are none
2747 
2748   Level: intermediate
2749 
2750 .seealso: PetscDSSetConstants(), PetscDSCreate()
2751 @*/
2752 PetscErrorCode PetscDSGetConstants(PetscDS prob, PetscInt *numConstants, const PetscScalar *constants[])
2753 {
2754   PetscFunctionBegin;
2755   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2756   if (numConstants) {PetscValidPointer(numConstants, 2); *numConstants = prob->numConstants;}
2757   if (constants)    {PetscValidPointer(constants, 3);    *constants    = prob->constants;}
2758   PetscFunctionReturn(0);
2759 }
2760 
2761 /*@C
2762   PetscDSSetConstants - Set the array of constants passed to point functions
2763 
2764   Not collective
2765 
2766   Input Parameters:
2767 + prob         - The PetscDS object
2768 . numConstants - The number of constants
2769 - constants    - The array of constants, NULL if there are none
2770 
2771   Level: intermediate
2772 
2773 .seealso: PetscDSGetConstants(), PetscDSCreate()
2774 @*/
2775 PetscErrorCode PetscDSSetConstants(PetscDS prob, PetscInt numConstants, PetscScalar constants[])
2776 {
2777   PetscErrorCode ierr;
2778 
2779   PetscFunctionBegin;
2780   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2781   if (numConstants != prob->numConstants) {
2782     ierr = PetscFree(prob->constants);CHKERRQ(ierr);
2783     prob->numConstants = numConstants;
2784     if (prob->numConstants) {
2785       ierr = PetscMalloc1(prob->numConstants, &prob->constants);CHKERRQ(ierr);
2786     } else {
2787       prob->constants = NULL;
2788     }
2789   }
2790   if (prob->numConstants) {
2791     PetscValidPointer(constants, 3);
2792     ierr = PetscArraycpy(prob->constants, constants, prob->numConstants);CHKERRQ(ierr);
2793   }
2794   PetscFunctionReturn(0);
2795 }
2796 
2797 /*@
2798   PetscDSGetFieldIndex - Returns the index of the given field
2799 
2800   Not collective
2801 
2802   Input Parameters:
2803 + prob - The PetscDS object
2804 - disc - The discretization object
2805 
2806   Output Parameter:
2807 . f - The field number
2808 
2809   Level: beginner
2810 
2811 .seealso: PetscGetDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
2812 @*/
2813 PetscErrorCode PetscDSGetFieldIndex(PetscDS prob, PetscObject disc, PetscInt *f)
2814 {
2815   PetscInt g;
2816 
2817   PetscFunctionBegin;
2818   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2819   PetscValidPointer(f, 3);
2820   *f = -1;
2821   for (g = 0; g < prob->Nf; ++g) {if (disc == prob->disc[g]) break;}
2822   if (g == prob->Nf) SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Field not found in PetscDS.");
2823   *f = g;
2824   PetscFunctionReturn(0);
2825 }
2826 
2827 /*@
2828   PetscDSGetFieldSize - Returns the size of the given field in the full space basis
2829 
2830   Not collective
2831 
2832   Input Parameters:
2833 + prob - The PetscDS object
2834 - f - The field number
2835 
2836   Output Parameter:
2837 . size - The size
2838 
2839   Level: beginner
2840 
2841 .seealso: PetscDSGetFieldOffset(), PetscDSGetNumFields(), PetscDSCreate()
2842 @*/
2843 PetscErrorCode PetscDSGetFieldSize(PetscDS prob, PetscInt f, PetscInt *size)
2844 {
2845   PetscErrorCode ierr;
2846 
2847   PetscFunctionBegin;
2848   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2849   PetscValidPointer(size, 3);
2850   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);
2851   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
2852   *size = prob->Nb[f];
2853   PetscFunctionReturn(0);
2854 }
2855 
2856 /*@
2857   PetscDSGetFieldOffset - Returns the offset of the given field in the full space basis
2858 
2859   Not collective
2860 
2861   Input Parameters:
2862 + prob - The PetscDS object
2863 - f - The field number
2864 
2865   Output Parameter:
2866 . off - The offset
2867 
2868   Level: beginner
2869 
2870 .seealso: PetscDSGetFieldSize(), PetscDSGetNumFields(), PetscDSCreate()
2871 @*/
2872 PetscErrorCode PetscDSGetFieldOffset(PetscDS prob, PetscInt f, PetscInt *off)
2873 {
2874   PetscInt       size, g;
2875   PetscErrorCode ierr;
2876 
2877   PetscFunctionBegin;
2878   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2879   PetscValidPointer(off, 3);
2880   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);
2881   *off = 0;
2882   for (g = 0; g < f; ++g) {
2883     ierr = PetscDSGetFieldSize(prob, g, &size);CHKERRQ(ierr);
2884     *off += size;
2885   }
2886   PetscFunctionReturn(0);
2887 }
2888 
2889 /*@
2890   PetscDSGetDimensions - Returns the size of the approximation space for each field on an evaluation point
2891 
2892   Not collective
2893 
2894   Input Parameter:
2895 . prob - The PetscDS object
2896 
2897   Output Parameter:
2898 . dimensions - The number of dimensions
2899 
2900   Level: beginner
2901 
2902 .seealso: PetscDSGetComponentOffsets(), PetscDSGetNumFields(), PetscDSCreate()
2903 @*/
2904 PetscErrorCode PetscDSGetDimensions(PetscDS prob, PetscInt *dimensions[])
2905 {
2906   PetscErrorCode ierr;
2907 
2908   PetscFunctionBegin;
2909   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2910   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
2911   PetscValidPointer(dimensions, 2);
2912   *dimensions = prob->Nb;
2913   PetscFunctionReturn(0);
2914 }
2915 
2916 /*@
2917   PetscDSGetComponents - Returns the number of components for each field on an evaluation point
2918 
2919   Not collective
2920 
2921   Input Parameter:
2922 . prob - The PetscDS object
2923 
2924   Output Parameter:
2925 . components - The number of components
2926 
2927   Level: beginner
2928 
2929 .seealso: PetscDSGetComponentOffsets(), PetscDSGetNumFields(), PetscDSCreate()
2930 @*/
2931 PetscErrorCode PetscDSGetComponents(PetscDS prob, PetscInt *components[])
2932 {
2933   PetscErrorCode ierr;
2934 
2935   PetscFunctionBegin;
2936   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2937   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
2938   PetscValidPointer(components, 2);
2939   *components = prob->Nc;
2940   PetscFunctionReturn(0);
2941 }
2942 
2943 /*@
2944   PetscDSGetComponentOffset - Returns the offset of the given field on an evaluation point
2945 
2946   Not collective
2947 
2948   Input Parameters:
2949 + prob - The PetscDS object
2950 - f - The field number
2951 
2952   Output Parameter:
2953 . off - The offset
2954 
2955   Level: beginner
2956 
2957 .seealso: PetscDSGetNumFields(), PetscDSCreate()
2958 @*/
2959 PetscErrorCode PetscDSGetComponentOffset(PetscDS prob, PetscInt f, PetscInt *off)
2960 {
2961   PetscFunctionBegin;
2962   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2963   PetscValidPointer(off, 3);
2964   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);
2965   *off = prob->off[f];
2966   PetscFunctionReturn(0);
2967 }
2968 
2969 /*@
2970   PetscDSGetComponentOffsets - Returns the offset of each field on an evaluation point
2971 
2972   Not collective
2973 
2974   Input Parameter:
2975 . prob - The PetscDS object
2976 
2977   Output Parameter:
2978 . offsets - The offsets
2979 
2980   Level: beginner
2981 
2982 .seealso: PetscDSGetNumFields(), PetscDSCreate()
2983 @*/
2984 PetscErrorCode PetscDSGetComponentOffsets(PetscDS prob, PetscInt *offsets[])
2985 {
2986   PetscFunctionBegin;
2987   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
2988   PetscValidPointer(offsets, 2);
2989   *offsets = prob->off;
2990   PetscFunctionReturn(0);
2991 }
2992 
2993 /*@
2994   PetscDSGetComponentDerivativeOffsets - Returns the offset of each field derivative on an evaluation point
2995 
2996   Not collective
2997 
2998   Input Parameter:
2999 . prob - The PetscDS object
3000 
3001   Output Parameter:
3002 . offsets - The offsets
3003 
3004   Level: beginner
3005 
3006 .seealso: PetscDSGetNumFields(), PetscDSCreate()
3007 @*/
3008 PetscErrorCode PetscDSGetComponentDerivativeOffsets(PetscDS prob, PetscInt *offsets[])
3009 {
3010   PetscFunctionBegin;
3011   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
3012   PetscValidPointer(offsets, 2);
3013   *offsets = prob->offDer;
3014   PetscFunctionReturn(0);
3015 }
3016 
3017 /*@C
3018   PetscDSGetTabulation - Return the basis tabulation at quadrature points for the volume discretization
3019 
3020   Not collective
3021 
3022   Input Parameter:
3023 . prob - The PetscDS object
3024 
3025   Output Parameter:
3026 . T - The basis function and derivatives tabulation at quadrature points for each field
3027 
3028   Level: intermediate
3029 
3030 .seealso: PetscDSCreate()
3031 @*/
3032 PetscErrorCode PetscDSGetTabulation(PetscDS prob, PetscTabulation *T[])
3033 {
3034   PetscErrorCode ierr;
3035 
3036   PetscFunctionBegin;
3037   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
3038   PetscValidPointer(T, 2);
3039   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
3040   *T = prob->T;
3041   PetscFunctionReturn(0);
3042 }
3043 
3044 /*@C
3045   PetscDSGetFaceTabulation - Return the basis tabulation at quadrature points on the faces
3046 
3047   Not collective
3048 
3049   Input Parameter:
3050 . prob - The PetscDS object
3051 
3052   Output Parameter:
3053 . Tf - The basis function and derviative tabulation on each local face at quadrature points for each and field
3054 
3055   Level: intermediate
3056 
3057 .seealso: PetscDSGetTabulation(), PetscDSCreate()
3058 @*/
3059 PetscErrorCode PetscDSGetFaceTabulation(PetscDS prob, PetscTabulation *Tf[])
3060 {
3061   PetscErrorCode ierr;
3062 
3063   PetscFunctionBegin;
3064   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
3065   PetscValidPointer(Tf, 2);
3066   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
3067   *Tf = prob->Tf;
3068   PetscFunctionReturn(0);
3069 }
3070 
3071 PetscErrorCode PetscDSGetEvaluationArrays(PetscDS prob, PetscScalar **u, PetscScalar **u_t, PetscScalar **u_x)
3072 {
3073   PetscErrorCode ierr;
3074 
3075   PetscFunctionBegin;
3076   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
3077   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
3078   if (u)   {PetscValidPointer(u, 2);   *u   = prob->u;}
3079   if (u_t) {PetscValidPointer(u_t, 3); *u_t = prob->u_t;}
3080   if (u_x) {PetscValidPointer(u_x, 4); *u_x = prob->u_x;}
3081   PetscFunctionReturn(0);
3082 }
3083 
3084 PetscErrorCode PetscDSGetWeakFormArrays(PetscDS prob, PetscScalar **f0, PetscScalar **f1, PetscScalar **g0, PetscScalar **g1, PetscScalar **g2, PetscScalar **g3)
3085 {
3086   PetscErrorCode ierr;
3087 
3088   PetscFunctionBegin;
3089   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
3090   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
3091   if (f0) {PetscValidPointer(f0, 2); *f0 = prob->f0;}
3092   if (f1) {PetscValidPointer(f1, 3); *f1 = prob->f1;}
3093   if (g0) {PetscValidPointer(g0, 4); *g0 = prob->g0;}
3094   if (g1) {PetscValidPointer(g1, 5); *g1 = prob->g1;}
3095   if (g2) {PetscValidPointer(g2, 6); *g2 = prob->g2;}
3096   if (g3) {PetscValidPointer(g3, 7); *g3 = prob->g3;}
3097   PetscFunctionReturn(0);
3098 }
3099 
3100 PetscErrorCode PetscDSGetWorkspace(PetscDS prob, PetscReal **x, PetscScalar **basisReal, PetscScalar **basisDerReal, PetscScalar **testReal, PetscScalar **testDerReal)
3101 {
3102   PetscErrorCode ierr;
3103 
3104   PetscFunctionBegin;
3105   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
3106   ierr = PetscDSSetUp(prob);CHKERRQ(ierr);
3107   if (x)            {PetscValidPointer(x, 2);            *x            = prob->x;}
3108   if (basisReal)    {PetscValidPointer(basisReal, 3);    *basisReal    = prob->basisReal;}
3109   if (basisDerReal) {PetscValidPointer(basisDerReal, 4); *basisDerReal = prob->basisDerReal;}
3110   if (testReal)     {PetscValidPointer(testReal, 5);     *testReal     = prob->testReal;}
3111   if (testDerReal)  {PetscValidPointer(testDerReal, 6);  *testDerReal  = prob->testDerReal;}
3112   PetscFunctionReturn(0);
3113 }
3114 
3115 /*@C
3116   PetscDSAddBoundary - Add a boundary condition to the model. The pointwise functions are used to provide boundary values for essential boundary conditions. In FEM, they are acting upon by dual basis functionals to generate FEM coefficients which are fixed. Natural boundary conditions signal to PETSc that boundary integrals should be performaed, using the kernels from PetscDSSetBdResidual().
3117 
3118   Collective on ds
3119 
3120   Input Parameters:
3121 + ds       - The PetscDS object
3122 . type     - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
3123 . name     - The BC name
3124 . label    - The label defining constrained points
3125 . Nv       - The number of DMLabel values for constrained points
3126 . values   - An array of label values for constrained points
3127 . field    - The field to constrain
3128 . Nc       - The number of constrained field components (0 will constrain all fields)
3129 . comps    - An array of constrained component numbers
3130 . bcFunc   - A pointwise function giving boundary values
3131 . bcFunc_t - A pointwise function giving the time derviative of the boundary values, or NULL
3132 - ctx      - An optional user context for bcFunc
3133 
3134   Output Parameters:
3135 - bd       - The boundary number
3136 
3137   Options Database Keys:
3138 + -bc_<boundary name> <num> - Overrides the boundary ids
3139 - -bc_<boundary name>_comp <num> - Overrides the boundary components
3140 
3141   Note:
3142   Both bcFunc abd bcFunc_t will depend on the boundary condition type. If the type if DM_BC_ESSENTIAL, Then the calling sequence is:
3143 
3144 $ bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])
3145 
3146   If the type is DM_BC_ESSENTIAL_FIELD or other _FIELD value, then the calling sequence is:
3147 
3148 $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
3149 $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
3150 $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
3151 $        PetscReal time, const PetscReal x[], PetscScalar bcval[])
3152 
3153 + dim - the spatial dimension
3154 . Nf - the number of fields
3155 . uOff - the offset into u[] and u_t[] for each field
3156 . uOff_x - the offset into u_x[] for each field
3157 . u - each field evaluated at the current point
3158 . u_t - the time derivative of each field evaluated at the current point
3159 . u_x - the gradient of each field evaluated at the current point
3160 . aOff - the offset into a[] and a_t[] for each auxiliary field
3161 . aOff_x - the offset into a_x[] for each auxiliary field
3162 . a - each auxiliary field evaluated at the current point
3163 . a_t - the time derivative of each auxiliary field evaluated at the current point
3164 . a_x - the gradient of auxiliary each field evaluated at the current point
3165 . t - current time
3166 . x - coordinates of the current point
3167 . numConstants - number of constant parameters
3168 . constants - constant parameters
3169 - bcval - output values at the current point
3170 
3171   Level: developer
3172 
3173 .seealso: PetscDSAddBoundaryByName(), PetscDSGetBoundary(), PetscDSSetResidual(), PetscDSSetBdResidual()
3174 @*/
3175 PetscErrorCode PetscDSAddBoundary(PetscDS ds, DMBoundaryConditionType type, const char name[], DMLabel label, PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx, PetscInt *bd)
3176 {
3177   DSBoundary     head = ds->boundary, b;
3178   PetscInt       n    = 0;
3179   const char    *lname;
3180   PetscErrorCode ierr;
3181 
3182   PetscFunctionBegin;
3183   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
3184   PetscValidLogicalCollectiveEnum(ds, type, 2);
3185   PetscValidCharPointer(name, 3);
3186   PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4);
3187   PetscValidLogicalCollectiveInt(ds, Nv, 5);
3188   PetscValidLogicalCollectiveInt(ds, field, 7);
3189   PetscValidLogicalCollectiveInt(ds, Nc, 8);
3190   ierr = PetscNew(&b);CHKERRQ(ierr);
3191   ierr = PetscStrallocpy(name, (char **) &b->name);CHKERRQ(ierr);
3192   ierr = PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf);CHKERRQ(ierr);
3193   ierr = PetscWeakFormSetNumFields(b->wf, ds->Nf);CHKERRQ(ierr);
3194   ierr = PetscMalloc1(Nv, &b->values);CHKERRQ(ierr);
3195   if (Nv) {ierr = PetscArraycpy(b->values, values, Nv);CHKERRQ(ierr);}
3196   ierr = PetscMalloc1(Nc, &b->comps);CHKERRQ(ierr);
3197   if (Nc) {ierr = PetscArraycpy(b->comps, comps, Nc);CHKERRQ(ierr);}
3198   ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr);
3199   ierr = PetscStrallocpy(lname, (char **) &b->lname);CHKERRQ(ierr);
3200   b->type   = type;
3201   b->label  = label;
3202   b->Nv     = Nv;
3203   b->field  = field;
3204   b->Nc     = Nc;
3205   b->func   = bcFunc;
3206   b->func_t = bcFunc_t;
3207   b->ctx    = ctx;
3208   b->next   = NULL;
3209   /* Append to linked list so that we can preserve the order */
3210   if (!head) ds->boundary = b;
3211   while (head) {
3212     if (!head->next) {
3213       head->next = b;
3214       head       = b;
3215     }
3216     head = head->next;
3217     ++n;
3218   }
3219   if (bd) {PetscValidIntPointer(bd, 13); *bd = n;}
3220   PetscFunctionReturn(0);
3221 }
3222 
3223 /*@C
3224   PetscDSAddBoundaryByName - Add a boundary condition to the model. The pointwise functions are used to provide boundary values for essential boundary conditions. In FEM, they are acting upon by dual basis functionals to generate FEM coefficients which are fixed. Natural boundary conditions signal to PETSc that boundary integrals should be performaed, using the kernels from PetscDSSetBdResidual().
3225 
3226   Collective on ds
3227 
3228   Input Parameters:
3229 + ds       - The PetscDS object
3230 . type     - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
3231 . name     - The BC name
3232 . lname    - The naem of the label defining constrained points
3233 . Nv       - The number of DMLabel values for constrained points
3234 . values   - An array of label values for constrained points
3235 . field    - The field to constrain
3236 . Nc       - The number of constrained field components (0 will constrain all fields)
3237 . comps    - An array of constrained component numbers
3238 . bcFunc   - A pointwise function giving boundary values
3239 . bcFunc_t - A pointwise function giving the time derviative of the boundary values, or NULL
3240 - ctx      - An optional user context for bcFunc
3241 
3242   Output Parameters:
3243 - bd       - The boundary number
3244 
3245   Options Database Keys:
3246 + -bc_<boundary name> <num> - Overrides the boundary ids
3247 - -bc_<boundary name>_comp <num> - Overrides the boundary components
3248 
3249   Note:
3250   This function should only be used with DMForest currently, since labels cannot be defined before the underlygin Plex is built.
3251 
3252   Both bcFunc abd bcFunc_t will depend on the boundary condition type. If the type if DM_BC_ESSENTIAL, Then the calling sequence is:
3253 
3254 $ bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])
3255 
3256   If the type is DM_BC_ESSENTIAL_FIELD or other _FIELD value, then the calling sequence is:
3257 
3258 $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
3259 $        const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
3260 $        const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
3261 $        PetscReal time, const PetscReal x[], PetscScalar bcval[])
3262 
3263 + dim - the spatial dimension
3264 . Nf - the number of fields
3265 . uOff - the offset into u[] and u_t[] for each field
3266 . uOff_x - the offset into u_x[] for each field
3267 . u - each field evaluated at the current point
3268 . u_t - the time derivative of each field evaluated at the current point
3269 . u_x - the gradient of each field evaluated at the current point
3270 . aOff - the offset into a[] and a_t[] for each auxiliary field
3271 . aOff_x - the offset into a_x[] for each auxiliary field
3272 . a - each auxiliary field evaluated at the current point
3273 . a_t - the time derivative of each auxiliary field evaluated at the current point
3274 . a_x - the gradient of auxiliary each field evaluated at the current point
3275 . t - current time
3276 . x - coordinates of the current point
3277 . numConstants - number of constant parameters
3278 . constants - constant parameters
3279 - bcval - output values at the current point
3280 
3281   Level: developer
3282 
3283 .seealso: PetscDSAddBoundary(), PetscDSGetBoundary(), PetscDSSetResidual(), PetscDSSetBdResidual()
3284 @*/
3285 PetscErrorCode PetscDSAddBoundaryByName(PetscDS ds, DMBoundaryConditionType type, const char name[], const char lname[], PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx, PetscInt *bd)
3286 {
3287   DSBoundary     head = ds->boundary, b;
3288   PetscInt       n    = 0;
3289   PetscErrorCode ierr;
3290 
3291   PetscFunctionBegin;
3292   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
3293   PetscValidLogicalCollectiveEnum(ds, type, 2);
3294   PetscValidCharPointer(name, 3);
3295   PetscValidCharPointer(lname, 4);
3296   PetscValidLogicalCollectiveInt(ds, Nv, 5);
3297   PetscValidLogicalCollectiveInt(ds, field, 7);
3298   PetscValidLogicalCollectiveInt(ds, Nc, 8);
3299   ierr = PetscNew(&b);CHKERRQ(ierr);
3300   ierr = PetscStrallocpy(name, (char **) &b->name);CHKERRQ(ierr);
3301   ierr = PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf);CHKERRQ(ierr);
3302   ierr = PetscWeakFormSetNumFields(b->wf, ds->Nf);CHKERRQ(ierr);
3303   ierr = PetscMalloc1(Nv, &b->values);CHKERRQ(ierr);
3304   if (Nv) {ierr = PetscArraycpy(b->values, values, Nv);CHKERRQ(ierr);}
3305   ierr = PetscMalloc1(Nc, &b->comps);CHKERRQ(ierr);
3306   if (Nc) {ierr = PetscArraycpy(b->comps, comps, Nc);CHKERRQ(ierr);}
3307   ierr = PetscStrallocpy(lname, (char **) &b->lname);CHKERRQ(ierr);
3308   b->type   = type;
3309   b->label  = NULL;
3310   b->Nv     = Nv;
3311   b->field  = field;
3312   b->Nc     = Nc;
3313   b->func   = bcFunc;
3314   b->func_t = bcFunc_t;
3315   b->ctx    = ctx;
3316   b->next   = NULL;
3317   /* Append to linked list so that we can preserve the order */
3318   if (!head) ds->boundary = b;
3319   while (head) {
3320     if (!head->next) {
3321       head->next = b;
3322       head       = b;
3323     }
3324     head = head->next;
3325     ++n;
3326   }
3327   if (bd) {PetscValidIntPointer(bd, 13); *bd = n;}
3328   PetscFunctionReturn(0);
3329 }
3330 
3331 /*@C
3332   PetscDSUpdateBoundary - Change a boundary condition for the model. The pointwise functions are used to provide boundary values for essential boundary conditions. In FEM, they are acting upon by dual basis functionals to generate FEM coefficients which are fixed. Natural boundary conditions signal to PETSc that boundary integrals should be performaed, using the kernels from PetscDSSetBdResidual().
3333 
3334   Input Parameters:
3335 + ds       - The PetscDS object
3336 . bd       - The boundary condition number
3337 . type     - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
3338 . name     - The BC name
3339 . label    - The label defining constrained points
3340 . Nv       - The number of DMLabel ids for constrained points
3341 . values   - An array of ids for constrained points
3342 . field    - The field to constrain
3343 . Nc       - The number of constrained field components
3344 . comps    - An array of constrained component numbers
3345 . bcFunc   - A pointwise function giving boundary values
3346 . bcFunc_t - A pointwise function giving the time derviative of the boundary values, or NULL
3347 - ctx      - An optional user context for bcFunc
3348 
3349   Note:
3350   The boundary condition number is the order in which it was registered. The user can get the number of boundary conditions from PetscDSGetNumBoundary(). See PetscDSAddBoundary() for a description of the calling sequences for the callbacks.
3351 
3352   Level: developer
3353 
3354 .seealso: PetscDSAddBoundary(), PetscDSGetBoundary(), PetscDSGetNumBoundary()
3355 @*/
3356 PetscErrorCode PetscDSUpdateBoundary(PetscDS ds, PetscInt bd, DMBoundaryConditionType type, const char name[], DMLabel label, PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx)
3357 {
3358   DSBoundary     b = ds->boundary;
3359   PetscInt       n = 0;
3360   PetscErrorCode ierr;
3361 
3362   PetscFunctionBegin;
3363   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
3364   while (b) {
3365     if (n == bd) break;
3366     b = b->next;
3367     ++n;
3368   }
3369   if (!b) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n);
3370   if (name) {
3371     ierr = PetscFree(b->name);CHKERRQ(ierr);
3372     ierr = PetscStrallocpy(name, (char **) &b->name);CHKERRQ(ierr);
3373   }
3374   b->type = type;
3375   if (label) {
3376     const char *name;
3377 
3378     b->label = label;
3379     ierr = PetscFree(b->lname);CHKERRQ(ierr);
3380     ierr = PetscObjectGetName((PetscObject) label, &name);CHKERRQ(ierr);
3381     ierr = PetscStrallocpy(name, (char **) &b->lname);CHKERRQ(ierr);
3382   }
3383   if (Nv >= 0) {
3384     b->Nv = Nv;
3385     ierr = PetscFree(b->values);CHKERRQ(ierr);
3386     ierr = PetscMalloc1(Nv, &b->values);CHKERRQ(ierr);
3387     if (Nv) {ierr = PetscArraycpy(b->values, values, Nv);CHKERRQ(ierr);}
3388   }
3389   if (field >= 0) b->field = field;
3390   if (Nc >= 0) {
3391     b->Nc = Nc;
3392     ierr = PetscFree(b->comps);CHKERRQ(ierr);
3393     ierr = PetscMalloc1(Nc, &b->comps);CHKERRQ(ierr);
3394     if (Nc) {ierr = PetscArraycpy(b->comps, comps, Nc);CHKERRQ(ierr);}
3395   }
3396   if (bcFunc)   b->func   = bcFunc;
3397   if (bcFunc_t) b->func_t = bcFunc_t;
3398   if (ctx)      b->ctx    = ctx;
3399   PetscFunctionReturn(0);
3400 }
3401 
3402 /*@
3403   PetscDSGetNumBoundary - Get the number of registered BC
3404 
3405   Input Parameters:
3406 . ds - The PetscDS object
3407 
3408   Output Parameters:
3409 . numBd - The number of BC
3410 
3411   Level: intermediate
3412 
3413 .seealso: PetscDSAddBoundary(), PetscDSGetBoundary()
3414 @*/
3415 PetscErrorCode PetscDSGetNumBoundary(PetscDS ds, PetscInt *numBd)
3416 {
3417   DSBoundary b = ds->boundary;
3418 
3419   PetscFunctionBegin;
3420   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
3421   PetscValidPointer(numBd, 2);
3422   *numBd = 0;
3423   while (b) {++(*numBd); b = b->next;}
3424   PetscFunctionReturn(0);
3425 }
3426 
3427 /*@C
3428   PetscDSGetBoundary - Gets a boundary condition to the model
3429 
3430   Input Parameters:
3431 + ds          - The PetscDS object
3432 - bd          - The BC number
3433 
3434   Output Parameters:
3435 + wf       - The PetscWeakForm holding the pointwise functions
3436 . type     - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
3437 . name     - The BC name
3438 . label    - The label defining constrained points
3439 . Nv       - The number of DMLabel ids for constrained points
3440 . values   - An array of ids for constrained points
3441 . field    - The field to constrain
3442 . Nc       - The number of constrained field components
3443 . comps    - An array of constrained component numbers
3444 . bcFunc   - A pointwise function giving boundary values
3445 . bcFunc_t - A pointwise function giving the time derviative of the boundary values
3446 - ctx      - An optional user context for bcFunc
3447 
3448   Options Database Keys:
3449 + -bc_<boundary name> <num> - Overrides the boundary ids
3450 - -bc_<boundary name>_comp <num> - Overrides the boundary components
3451 
3452   Level: developer
3453 
3454 .seealso: PetscDSAddBoundary()
3455 @*/
3456 PetscErrorCode PetscDSGetBoundary(PetscDS ds, PetscInt bd, PetscWeakForm *wf, DMBoundaryConditionType *type, const char *name[], DMLabel *label, PetscInt *Nv, const PetscInt *values[], PetscInt *field, PetscInt *Nc, const PetscInt *comps[], void (**func)(void), void (**func_t)(void), void **ctx)
3457 {
3458   DSBoundary b = ds->boundary;
3459   PetscInt   n = 0;
3460 
3461   PetscFunctionBegin;
3462   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
3463   while (b) {
3464     if (n == bd) break;
3465     b = b->next;
3466     ++n;
3467   }
3468   if (!b) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n);
3469   if (wf) {
3470     PetscValidPointer(wf, 3);
3471     *wf = b->wf;
3472   }
3473   if (type) {
3474     PetscValidPointer(type, 4);
3475     *type = b->type;
3476   }
3477   if (name) {
3478     PetscValidPointer(name, 5);
3479     *name = b->name;
3480   }
3481   if (label) {
3482     PetscValidPointer(label, 6);
3483     *label = b->label;
3484   }
3485   if (Nv) {
3486     PetscValidIntPointer(Nv, 7);
3487     *Nv = b->Nv;
3488   }
3489   if (values) {
3490     PetscValidPointer(values, 8);
3491     *values = b->values;
3492   }
3493   if (field) {
3494     PetscValidIntPointer(field, 9);
3495     *field = b->field;
3496   }
3497   if (Nc) {
3498     PetscValidIntPointer(Nc, 10);
3499     *Nc = b->Nc;
3500   }
3501   if (comps) {
3502     PetscValidPointer(comps, 11);
3503     *comps = b->comps;
3504   }
3505   if (func) {
3506     PetscValidPointer(func, 12);
3507     *func = b->func;
3508   }
3509   if (func_t) {
3510     PetscValidPointer(func_t, 13);
3511     *func_t = b->func_t;
3512   }
3513   if (ctx) {
3514     PetscValidPointer(ctx, 14);
3515     *ctx = b->ctx;
3516   }
3517   PetscFunctionReturn(0);
3518 }
3519 
3520 static PetscErrorCode DSBoundaryDuplicate_Internal(DSBoundary b, DSBoundary *bNew)
3521 {
3522   PetscErrorCode ierr;
3523 
3524   PetscFunctionBegin;
3525   ierr = PetscNew(bNew);CHKERRQ(ierr);
3526   ierr = PetscWeakFormCreate(PETSC_COMM_SELF, &(*bNew)->wf);CHKERRQ(ierr);
3527   ierr = PetscWeakFormCopy(b->wf, (*bNew)->wf);CHKERRQ(ierr);
3528   ierr = PetscStrallocpy(b->name,(char **) &((*bNew)->name));CHKERRQ(ierr);
3529   ierr = PetscStrallocpy(b->lname,(char **) &((*bNew)->lname));CHKERRQ(ierr);
3530   (*bNew)->type   = b->type;
3531   (*bNew)->label  = b->label;
3532   (*bNew)->Nv     = b->Nv;
3533   ierr = PetscMalloc1(b->Nv, &(*bNew)->values);CHKERRQ(ierr);
3534   ierr = PetscArraycpy((*bNew)->values, b->values, b->Nv);CHKERRQ(ierr);
3535   (*bNew)->field  = b->field;
3536   (*bNew)->Nc     = b->Nc;
3537   ierr = PetscMalloc1(b->Nc, &(*bNew)->comps);CHKERRQ(ierr);
3538   ierr = PetscArraycpy((*bNew)->comps, b->comps, b->Nc);CHKERRQ(ierr);
3539   (*bNew)->func   = b->func;
3540   (*bNew)->func_t = b->func_t;
3541   (*bNew)->ctx    = b->ctx;
3542   PetscFunctionReturn(0);
3543 }
3544 
3545 /*@
3546   PetscDSCopyBoundary - Copy all boundary condition objects to the new problem
3547 
3548   Not collective
3549 
3550   Input Parameters:
3551 + ds        - The source PetscDS object
3552 . numFields - The number of selected fields, or PETSC_DEFAULT for all fields
3553 - fields    - The selected fields, or NULL for all fields
3554 
3555   Output Parameter:
3556 . newds     - The target PetscDS, now with a copy of the boundary conditions
3557 
3558   Level: intermediate
3559 
3560 .seealso: PetscDSCopyEquations(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
3561 @*/
3562 PetscErrorCode PetscDSCopyBoundary(PetscDS ds, PetscInt numFields, const PetscInt fields[], PetscDS newds)
3563 {
3564   DSBoundary     b, *lastnext;
3565   PetscErrorCode ierr;
3566 
3567   PetscFunctionBegin;
3568   PetscValidHeaderSpecific(ds,    PETSCDS_CLASSID, 1);
3569   PetscValidHeaderSpecific(newds, PETSCDS_CLASSID, 4);
3570   if (ds == newds) PetscFunctionReturn(0);
3571   ierr = PetscDSDestroyBoundary(newds);CHKERRQ(ierr);
3572   lastnext = &(newds->boundary);
3573   for (b = ds->boundary; b; b = b->next) {
3574     DSBoundary bNew;
3575     PetscInt   fieldNew = -1;
3576 
3577     if (numFields > 0 && fields) {
3578       PetscInt f;
3579 
3580       for (f = 0; f < numFields; ++f) if (b->field == fields[f]) break;
3581       if (f == numFields) continue;
3582       fieldNew = f;
3583     }
3584     ierr = DSBoundaryDuplicate_Internal(b, &bNew);CHKERRQ(ierr);
3585     bNew->field = fieldNew < 0 ? b->field : fieldNew;
3586     *lastnext = bNew;
3587     lastnext  = &(bNew->next);
3588   }
3589   PetscFunctionReturn(0);
3590 }
3591 
3592 /*@
3593   PetscDSDestroyBoundary - Remove all DMBoundary objects from the PetscDS
3594 
3595   Not collective
3596 
3597   Input Parameter:
3598 . ds - The PetscDS object
3599 
3600   Level: intermediate
3601 
3602 .seealso: PetscDSCopyBoundary(), PetscDSCopyEquations()
3603 @*/
3604 PetscErrorCode PetscDSDestroyBoundary(PetscDS ds)
3605 {
3606   DSBoundary     next = ds->boundary;
3607   PetscErrorCode ierr;
3608 
3609   PetscFunctionBegin;
3610   while (next) {
3611     DSBoundary b = next;
3612 
3613     next = b->next;
3614     ierr = PetscWeakFormDestroy(&b->wf);CHKERRQ(ierr);
3615     ierr = PetscFree(b->name);CHKERRQ(ierr);
3616     ierr = PetscFree(b->lname);CHKERRQ(ierr);
3617     ierr = PetscFree(b->values);CHKERRQ(ierr);
3618     ierr = PetscFree(b->comps);CHKERRQ(ierr);
3619     ierr = PetscFree(b);CHKERRQ(ierr);
3620   }
3621   PetscFunctionReturn(0);
3622 }
3623 
3624 /*@
3625   PetscDSSelectDiscretizations - Copy discretizations to the new problem with different field layout
3626 
3627   Not collective
3628 
3629   Input Parameter:
3630 + prob - The PetscDS object
3631 . numFields - Number of new fields
3632 - fields - Old field number for each new field
3633 
3634   Output Parameter:
3635 . newprob - The PetscDS copy
3636 
3637   Level: intermediate
3638 
3639 .seealso: PetscDSSelectEquations(), PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
3640 @*/
3641 PetscErrorCode PetscDSSelectDiscretizations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob)
3642 {
3643   PetscInt       Nf, Nfn, fn;
3644   PetscErrorCode ierr;
3645 
3646   PetscFunctionBegin;
3647   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
3648   if (fields) PetscValidPointer(fields, 3);
3649   PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 4);
3650   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
3651   ierr = PetscDSGetNumFields(newprob, &Nfn);CHKERRQ(ierr);
3652   numFields = numFields < 0 ? Nf : numFields;
3653   for (fn = 0; fn < numFields; ++fn) {
3654     const PetscInt f = fields ? fields[fn] : fn;
3655     PetscObject    disc;
3656 
3657     if (f >= Nf) continue;
3658     ierr = PetscDSGetDiscretization(prob, f, &disc);CHKERRQ(ierr);
3659     ierr = PetscDSSetDiscretization(newprob, fn, disc);CHKERRQ(ierr);
3660   }
3661   PetscFunctionReturn(0);
3662 }
3663 
3664 /*@
3665   PetscDSSelectEquations - Copy pointwise function pointers to the new problem with different field layout
3666 
3667   Not collective
3668 
3669   Input Parameter:
3670 + prob - The PetscDS object
3671 . numFields - Number of new fields
3672 - fields - Old field number for each new field
3673 
3674   Output Parameter:
3675 . newprob - The PetscDS copy
3676 
3677   Level: intermediate
3678 
3679 .seealso: PetscDSSelectDiscretizations(), PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
3680 @*/
3681 PetscErrorCode PetscDSSelectEquations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob)
3682 {
3683   PetscInt       Nf, Nfn, fn, gn;
3684   PetscErrorCode ierr;
3685 
3686   PetscFunctionBegin;
3687   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
3688   if (fields) PetscValidPointer(fields, 3);
3689   PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 4);
3690   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
3691   ierr = PetscDSGetNumFields(newprob, &Nfn);CHKERRQ(ierr);
3692   if (numFields > Nfn) SETERRQ2(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_SIZ, "Number of fields %D to transfer must not be greater then the total number of fields %D", numFields, Nfn);
3693   for (fn = 0; fn < numFields; ++fn) {
3694     const PetscInt   f = fields ? fields[fn] : fn;
3695     PetscPointFunc   obj;
3696     PetscPointFunc   f0, f1;
3697     PetscBdPointFunc f0Bd, f1Bd;
3698     PetscRiemannFunc r;
3699 
3700     if (f >= Nf) continue;
3701     ierr = PetscDSGetObjective(prob, f, &obj);CHKERRQ(ierr);
3702     ierr = PetscDSGetResidual(prob, f, &f0, &f1);CHKERRQ(ierr);
3703     ierr = PetscDSGetBdResidual(prob, f, &f0Bd, &f1Bd);CHKERRQ(ierr);
3704     ierr = PetscDSGetRiemannSolver(prob, f, &r);CHKERRQ(ierr);
3705     ierr = PetscDSSetObjective(newprob, fn, obj);CHKERRQ(ierr);
3706     ierr = PetscDSSetResidual(newprob, fn, f0, f1);CHKERRQ(ierr);
3707     ierr = PetscDSSetBdResidual(newprob, fn, f0Bd, f1Bd);CHKERRQ(ierr);
3708     ierr = PetscDSSetRiemannSolver(newprob, fn, r);CHKERRQ(ierr);
3709     for (gn = 0; gn < numFields; ++gn) {
3710       const PetscInt  g = fields ? fields[gn] : gn;
3711       PetscPointJac   g0, g1, g2, g3;
3712       PetscPointJac   g0p, g1p, g2p, g3p;
3713       PetscBdPointJac g0Bd, g1Bd, g2Bd, g3Bd;
3714 
3715       if (g >= Nf) continue;
3716       ierr = PetscDSGetJacobian(prob, f, g, &g0, &g1, &g2, &g3);CHKERRQ(ierr);
3717       ierr = PetscDSGetJacobianPreconditioner(prob, f, g, &g0p, &g1p, &g2p, &g3p);CHKERRQ(ierr);
3718       ierr = PetscDSGetBdJacobian(prob, f, g, &g0Bd, &g1Bd, &g2Bd, &g3Bd);CHKERRQ(ierr);
3719       ierr = PetscDSSetJacobian(newprob, fn, gn, g0, g1, g2, g3);CHKERRQ(ierr);
3720       ierr = PetscDSSetJacobianPreconditioner(newprob, fn, gn, g0p, g1p, g2p, g3p);CHKERRQ(ierr);
3721       ierr = PetscDSSetBdJacobian(newprob, fn, gn, g0Bd, g1Bd, g2Bd, g3Bd);CHKERRQ(ierr);
3722     }
3723   }
3724   PetscFunctionReturn(0);
3725 }
3726 
3727 /*@
3728   PetscDSCopyEquations - Copy all pointwise function pointers to the new problem
3729 
3730   Not collective
3731 
3732   Input Parameter:
3733 . prob - The PetscDS object
3734 
3735   Output Parameter:
3736 . newprob - The PetscDS copy
3737 
3738   Level: intermediate
3739 
3740 .seealso: PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
3741 @*/
3742 PetscErrorCode PetscDSCopyEquations(PetscDS prob, PetscDS newprob)
3743 {
3744   PetscInt       Nf, Ng;
3745   PetscErrorCode ierr;
3746 
3747   PetscFunctionBegin;
3748   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
3749   PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 2);
3750   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
3751   ierr = PetscDSGetNumFields(newprob, &Ng);CHKERRQ(ierr);
3752   if (Nf != Ng) SETERRQ2(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_SIZ, "Number of fields must match %D != %D", Nf, Ng);
3753   ierr = PetscDSSelectEquations(prob, Nf, NULL, newprob);CHKERRQ(ierr);
3754   PetscFunctionReturn(0);
3755 }
3756 
3757 /*@
3758   PetscDSCopyConstants - Copy all constants to the new problem
3759 
3760   Not collective
3761 
3762   Input Parameter:
3763 . prob - The PetscDS object
3764 
3765   Output Parameter:
3766 . newprob - The PetscDS copy
3767 
3768   Level: intermediate
3769 
3770 .seealso: PetscDSCopyBoundary(), PetscDSCopyEquations(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
3771 @*/
3772 PetscErrorCode PetscDSCopyConstants(PetscDS prob, PetscDS newprob)
3773 {
3774   PetscInt           Nc;
3775   const PetscScalar *constants;
3776   PetscErrorCode     ierr;
3777 
3778   PetscFunctionBegin;
3779   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
3780   PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 2);
3781   ierr = PetscDSGetConstants(prob, &Nc, &constants);CHKERRQ(ierr);
3782   ierr = PetscDSSetConstants(newprob, Nc, (PetscScalar *) constants);CHKERRQ(ierr);
3783   PetscFunctionReturn(0);
3784 }
3785 
3786 /*@
3787   PetscDSCopyExactSolutions - Copy all exact solutions to the new problem
3788 
3789   Not collective
3790 
3791   Input Parameter:
3792 . ds - The PetscDS object
3793 
3794   Output Parameter:
3795 . newds - The PetscDS copy
3796 
3797   Level: intermediate
3798 
3799 .seealso: PetscDSCopyBoundary(), PetscDSCopyEquations(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
3800 @*/
3801 PetscErrorCode PetscDSCopyExactSolutions(PetscDS ds, PetscDS newds)
3802 {
3803   PetscSimplePointFunc sol;
3804   void                *ctx;
3805   PetscInt             Nf, f;
3806   PetscErrorCode       ierr;
3807 
3808   PetscFunctionBegin;
3809   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
3810   PetscValidHeaderSpecific(newds, PETSCDS_CLASSID, 2);
3811   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
3812   for (f = 0; f < Nf; ++f) {
3813     ierr = PetscDSGetExactSolution(ds,    f, &sol, &ctx);CHKERRQ(ierr);
3814     ierr = PetscDSSetExactSolution(newds, f,  sol,  ctx);CHKERRQ(ierr);
3815     ierr = PetscDSGetExactSolutionTimeDerivative(ds,    f, &sol, &ctx);CHKERRQ(ierr);
3816     ierr = PetscDSSetExactSolutionTimeDerivative(newds, f,  sol,  ctx);CHKERRQ(ierr);
3817   }
3818   PetscFunctionReturn(0);
3819 }
3820 
3821 PetscErrorCode PetscDSGetHeightSubspace(PetscDS prob, PetscInt height, PetscDS *subprob)
3822 {
3823   PetscInt       dim, Nf, f;
3824   PetscErrorCode ierr;
3825 
3826   PetscFunctionBegin;
3827   PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1);
3828   PetscValidPointer(subprob, 3);
3829   if (height == 0) {*subprob = prob; PetscFunctionReturn(0);}
3830   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
3831   ierr = PetscDSGetSpatialDimension(prob, &dim);CHKERRQ(ierr);
3832   if (height > dim) SETERRQ2(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_OUTOFRANGE, "DS can only handle height in [0, %D], not %D", dim, height);
3833   if (!prob->subprobs) {ierr = PetscCalloc1(dim, &prob->subprobs);CHKERRQ(ierr);}
3834   if (!prob->subprobs[height-1]) {
3835     PetscInt cdim;
3836 
3837     ierr = PetscDSCreate(PetscObjectComm((PetscObject) prob), &prob->subprobs[height-1]);CHKERRQ(ierr);
3838     ierr = PetscDSGetCoordinateDimension(prob, &cdim);CHKERRQ(ierr);
3839     ierr = PetscDSSetCoordinateDimension(prob->subprobs[height-1], cdim);CHKERRQ(ierr);
3840     for (f = 0; f < Nf; ++f) {
3841       PetscFE      subfe;
3842       PetscObject  obj;
3843       PetscClassId id;
3844 
3845       ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr);
3846       ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
3847       if (id == PETSCFE_CLASSID) {ierr = PetscFEGetHeightSubspace((PetscFE) obj, height, &subfe);CHKERRQ(ierr);}
3848       else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unsupported discretization type for field %d", f);
3849       ierr = PetscDSSetDiscretization(prob->subprobs[height-1], f, (PetscObject) subfe);CHKERRQ(ierr);
3850     }
3851   }
3852   *subprob = prob->subprobs[height-1];
3853   PetscFunctionReturn(0);
3854 }
3855 
3856 PetscErrorCode PetscDSGetDiscType_Internal(PetscDS ds, PetscInt f, PetscDiscType *disctype)
3857 {
3858   PetscObject    obj;
3859   PetscClassId   id;
3860   PetscInt       Nf;
3861   PetscErrorCode ierr;
3862 
3863   PetscFunctionBegin;
3864   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
3865   PetscValidPointer(disctype, 3);
3866   *disctype = PETSC_DISC_NONE;
3867   ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr);
3868   if (f >= Nf) SETERRQ2(PetscObjectComm((PetscObject) ds), PETSC_ERR_ARG_SIZ, "Field %D must be in [0, %D)", f, Nf);
3869   ierr = PetscDSGetDiscretization(ds, f, &obj);CHKERRQ(ierr);
3870   if (obj) {
3871     ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr);
3872     if (id == PETSCFE_CLASSID) *disctype = PETSC_DISC_FE;
3873     else                       *disctype = PETSC_DISC_FV;
3874   }
3875   PetscFunctionReturn(0);
3876 }
3877 
3878 static PetscErrorCode PetscDSDestroy_Basic(PetscDS ds)
3879 {
3880   PetscErrorCode ierr;
3881 
3882   PetscFunctionBegin;
3883   ierr = PetscFree(ds->data);CHKERRQ(ierr);
3884   PetscFunctionReturn(0);
3885 }
3886 
3887 static PetscErrorCode PetscDSInitialize_Basic(PetscDS ds)
3888 {
3889   PetscFunctionBegin;
3890   ds->ops->setfromoptions = NULL;
3891   ds->ops->setup          = NULL;
3892   ds->ops->view           = NULL;
3893   ds->ops->destroy        = PetscDSDestroy_Basic;
3894   PetscFunctionReturn(0);
3895 }
3896 
3897 /*MC
3898   PETSCDSBASIC = "basic" - A discrete system with pointwise residual and boundary residual functions
3899 
3900   Level: intermediate
3901 
3902 .seealso: PetscDSType, PetscDSCreate(), PetscDSSetType()
3903 M*/
3904 
3905 PETSC_EXTERN PetscErrorCode PetscDSCreate_Basic(PetscDS ds)
3906 {
3907   PetscDS_Basic *b;
3908   PetscErrorCode ierr;
3909 
3910   PetscFunctionBegin;
3911   PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1);
3912   ierr = PetscNewLog(ds, &b);CHKERRQ(ierr);
3913   ds->data = b;
3914 
3915   ierr = PetscDSInitialize_Basic(ds);CHKERRQ(ierr);
3916   PetscFunctionReturn(0);
3917 }
3918