Actual source code: dtds.c
1: #include <petsc/private/petscdsimpl.h>
3: PetscClassId PETSCDS_CLASSID = 0;
5: PetscFunctionList PetscDSList = NULL;
6: PetscBool PetscDSRegisterAllCalled = PETSC_FALSE;
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.
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.
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: */
21: /*@C
22: PetscDSRegister - Adds a new PetscDS implementation
24: Not Collective
26: Input Parameters:
27: + name - The name of a new user-defined creation routine
28: - create_func - The creation routine itself
30: Notes:
31: PetscDSRegister() may be called multiple times to add several user-defined PetscDSs
33: Sample usage:
34: .vb
35: PetscDSRegister("my_ds", MyPetscDSCreate);
36: .ve
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
48: Level: advanced
50: Not available from Fortran
52: .seealso: PetscDSRegisterAll(), PetscDSRegisterDestroy()
54: @*/
55: PetscErrorCode PetscDSRegister(const char sname[], PetscErrorCode (*function)(PetscDS))
56: {
60: PetscFunctionListAdd(&PetscDSList, sname, function);
61: return(0);
62: }
64: /*@C
65: PetscDSSetType - Builds a particular PetscDS
67: Collective on prob
69: Input Parameters:
70: + prob - The PetscDS object
71: - name - The kind of system
73: Options Database Key:
74: . -petscds_type <type> - Sets the PetscDS type; use -help for a list of available types
76: Level: intermediate
78: Not available from Fortran
80: .seealso: PetscDSGetType(), PetscDSCreate()
81: @*/
82: PetscErrorCode PetscDSSetType(PetscDS prob, PetscDSType name)
83: {
84: PetscErrorCode (*r)(PetscDS);
85: PetscBool match;
90: PetscObjectTypeCompare((PetscObject) prob, name, &match);
91: if (match) return(0);
93: PetscDSRegisterAll();
94: PetscFunctionListFind(PetscDSList, name, &r);
95: if (!r) SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDS type: %s", name);
97: if (prob->ops->destroy) {
98: (*prob->ops->destroy)(prob);
99: prob->ops->destroy = NULL;
100: }
101: (*r)(prob);
102: PetscObjectChangeTypeName((PetscObject) prob, name);
103: return(0);
104: }
106: /*@C
107: PetscDSGetType - Gets the PetscDS type name (as a string) from the object.
109: Not Collective
111: Input Parameter:
112: . prob - The PetscDS
114: Output Parameter:
115: . name - The PetscDS type name
117: Level: intermediate
119: Not available from Fortran
121: .seealso: PetscDSSetType(), PetscDSCreate()
122: @*/
123: PetscErrorCode PetscDSGetType(PetscDS prob, PetscDSType *name)
124: {
130: PetscDSRegisterAll();
131: *name = ((PetscObject) prob)->type_name;
132: return(0);
133: }
135: static PetscErrorCode PetscDSView_Ascii(PetscDS prob, PetscViewer viewer)
136: {
137: PetscViewerFormat format;
138: const PetscScalar *constants;
139: PetscInt numConstants, f;
140: PetscErrorCode ierr;
143: PetscViewerGetFormat(viewer, &format);
144: PetscViewerASCIIPrintf(viewer, "Discrete System with %d fields\n", prob->Nf);
145: PetscViewerASCIIPushTab(viewer);
146: PetscViewerASCIIPrintf(viewer, " cell total dim %D total comp %D\n", prob->totDim, prob->totComp);
147: if (prob->isHybrid) {PetscViewerASCIIPrintf(viewer, " hybrid cell\n");}
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;
156: PetscDSGetDiscretization(prob, f, &obj);
157: PetscObjectGetClassId(obj, &id);
158: PetscObjectGetName(obj, &name);
159: PetscViewerASCIIPrintf(viewer, "Field %s", name ? name : "<unknown>");
160: PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);
161: if (id == PETSCFE_CLASSID) {
162: PetscFEGetNumComponents((PetscFE) obj, &Nc);
163: PetscFEGetQuadrature((PetscFE) obj, &q);
164: PetscViewerASCIIPrintf(viewer, " FEM");
165: } else if (id == PETSCFV_CLASSID) {
166: PetscFVGetNumComponents((PetscFV) obj, &Nc);
167: PetscFVGetQuadrature((PetscFV) obj, &q);
168: PetscViewerASCIIPrintf(viewer, " FVM");
169: }
170: else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %D", f);
171: if (Nc > 1) {PetscViewerASCIIPrintf(viewer, "%D components", Nc);}
172: else {PetscViewerASCIIPrintf(viewer, "%D component ", Nc);}
173: if (prob->implicit[f]) {PetscViewerASCIIPrintf(viewer, " (implicit)");}
174: else {PetscViewerASCIIPrintf(viewer, " (explicit)");}
175: if (q) {
176: PetscQuadratureGetData(q, NULL, &Nqc, &Nq, NULL, NULL);
177: PetscViewerASCIIPrintf(viewer, " (Nq %D Nqc %D)", Nq, Nqc);
178: }
179: PetscViewerASCIIPrintf(viewer, " %D-jet", prob->jetDegree[f]);
180: PetscViewerASCIIPrintf(viewer, "\n");
181: PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);
182: PetscViewerASCIIPushTab(viewer);
183: if (id == PETSCFE_CLASSID) {PetscFEView((PetscFE) obj, viewer);}
184: else if (id == PETSCFV_CLASSID) {PetscFVView((PetscFV) obj, viewer);}
185: PetscViewerASCIIPopTab(viewer);
187: for (b = prob->boundary; b; b = b->next) {
188: const char *name;
189: PetscInt c, i;
191: if (b->field != f) continue;
192: PetscViewerASCIIPushTab(viewer);
193: PetscViewerASCIIPrintf(viewer, "Boundary %s (%s) %s\n", b->name, b->labelname, DMBoundaryConditionTypes[b->type]);
194: if (!b->numcomps) {
195: PetscViewerASCIIPrintf(viewer, " all components\n");
196: } else {
197: PetscViewerASCIIPrintf(viewer, " components: ");
198: PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);
199: for (c = 0; c < b->numcomps; ++c) {
200: if (c > 0) {PetscViewerASCIIPrintf(viewer, ", ");}
201: PetscViewerASCIIPrintf(viewer, "%D", b->comps[c]);
202: }
203: PetscViewerASCIIPrintf(viewer, "\n");
204: PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);
205: }
206: PetscViewerASCIIPrintf(viewer, " ids: ");
207: PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);
208: for (i = 0; i < b->numids; ++i) {
209: if (i > 0) {PetscViewerASCIIPrintf(viewer, ", ");}
210: PetscViewerASCIIPrintf(viewer, "%D", b->ids[i]);
211: }
212: PetscViewerASCIIPrintf(viewer, "\n");
213: PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);
214: if (b->func) {
215: PetscDLAddr(b->func, &name);
216: if (name) {PetscViewerASCIIPrintf(viewer, " func: %s\n", name);}
217: else {PetscViewerASCIIPrintf(viewer, " func: %p\n", b->func);}
218: }
219: if (b->func_t) {
220: PetscDLAddr(b->func_t, &name);
221: if (name) {PetscViewerASCIIPrintf(viewer, " func: %s\n", name);}
222: else {PetscViewerASCIIPrintf(viewer, " func: %p\n", b->func_t);}
223: }
224: PetscViewerASCIIPopTab(viewer);
225: }
226: }
227: PetscDSGetConstants(prob, &numConstants, &constants);
228: if (numConstants) {
229: PetscViewerASCIIPrintf(viewer, "%D constants\n", numConstants);
230: PetscViewerASCIIPushTab(viewer);
231: for (f = 0; f < numConstants; ++f) {PetscViewerASCIIPrintf(viewer, "%g\n", (double) PetscRealPart(constants[f]));}
232: PetscViewerASCIIPopTab(viewer);
233: }
234: PetscWeakFormView(prob->wf, viewer);
235: PetscViewerASCIIPopTab(viewer);
236: return(0);
237: }
239: /*@C
240: PetscDSViewFromOptions - View from Options
242: Collective on PetscDS
244: Input Parameters:
245: + A - the PetscDS object
246: . obj - Optional object
247: - name - command line option
249: Level: intermediate
250: .seealso: PetscDS, PetscDSView, PetscObjectViewFromOptions(), PetscDSCreate()
251: @*/
252: PetscErrorCode PetscDSViewFromOptions(PetscDS A,PetscObject obj,const char name[])
253: {
258: PetscObjectViewFromOptions((PetscObject)A,obj,name);
259: return(0);
260: }
262: /*@C
263: PetscDSView - Views a PetscDS
265: Collective on prob
267: Input Parameter:
268: + prob - the PetscDS object to view
269: - v - the viewer
271: Level: developer
273: .seealso PetscDSDestroy()
274: @*/
275: PetscErrorCode PetscDSView(PetscDS prob, PetscViewer v)
276: {
277: PetscBool iascii;
282: if (!v) {PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) prob), &v);}
284: PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &iascii);
285: if (iascii) {PetscDSView_Ascii(prob, v);}
286: if (prob->ops->view) {(*prob->ops->view)(prob, v);}
287: return(0);
288: }
290: /*@
291: PetscDSSetFromOptions - sets parameters in a PetscDS from the options database
293: Collective on prob
295: Input Parameter:
296: . prob - the PetscDS object to set options for
298: Options Database:
299: + -petscds_type <type> : Set the DS type
300: . -petscds_view <view opt> : View the DS
301: . -petscds_jac_pre : Turn formation of a separate Jacobian preconditioner on and off
302: . -bc_<name> <ids> : Specify a list of label ids for a boundary condition
303: - -bc_<name>_comp <comps> : Specify a list of field components to constrain for a boundary condition
305: Level: developer
307: .seealso PetscDSView()
308: @*/
309: PetscErrorCode PetscDSSetFromOptions(PetscDS prob)
310: {
311: DSBoundary b;
312: const char *defaultType;
313: char name[256];
314: PetscBool flg;
319: if (!((PetscObject) prob)->type_name) {
320: defaultType = PETSCDSBASIC;
321: } else {
322: defaultType = ((PetscObject) prob)->type_name;
323: }
324: PetscDSRegisterAll();
326: PetscObjectOptionsBegin((PetscObject) prob);
327: for (b = prob->boundary; b; b = b->next) {
328: char optname[1024];
329: PetscInt ids[1024], len = 1024;
330: PetscBool flg;
332: PetscSNPrintf(optname, sizeof(optname), "-bc_%s", b->name);
333: PetscMemzero(ids, sizeof(ids));
334: PetscOptionsIntArray(optname, "List of boundary IDs", "", ids, &len, &flg);
335: if (flg) {
336: b->numids = len;
337: PetscFree(b->ids);
338: PetscMalloc1(len, &b->ids);
339: PetscArraycpy(b->ids, ids, len);
340: }
341: len = 1024;
342: PetscSNPrintf(optname, sizeof(optname), "-bc_%s_comp", b->name);
343: PetscMemzero(ids, sizeof(ids));
344: PetscOptionsIntArray(optname, "List of boundary field components", "", ids, &len, &flg);
345: if (flg) {
346: b->numcomps = len;
347: PetscFree(b->comps);
348: PetscMalloc1(len, &b->comps);
349: PetscArraycpy(b->comps, ids, len);
350: }
351: }
352: PetscOptionsFList("-petscds_type", "Discrete System", "PetscDSSetType", PetscDSList, defaultType, name, 256, &flg);
353: if (flg) {
354: PetscDSSetType(prob, name);
355: } else if (!((PetscObject) prob)->type_name) {
356: PetscDSSetType(prob, defaultType);
357: }
358: PetscOptionsBool("-petscds_jac_pre", "Discrete System", "PetscDSUseJacobianPreconditioner", prob->useJacPre, &prob->useJacPre, &flg);
359: if (prob->ops->setfromoptions) {(*prob->ops->setfromoptions)(prob);}
360: /* process any options handlers added with PetscObjectAddOptionsHandler() */
361: PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) prob);
362: PetscOptionsEnd();
363: if (prob->Nf) {PetscDSViewFromOptions(prob, NULL, "-petscds_view");}
364: return(0);
365: }
367: /*@C
368: PetscDSSetUp - Construct data structures for the PetscDS
370: Collective on prob
372: Input Parameter:
373: . prob - the PetscDS object to setup
375: Level: developer
377: .seealso PetscDSView(), PetscDSDestroy()
378: @*/
379: PetscErrorCode PetscDSSetUp(PetscDS prob)
380: {
381: const PetscInt Nf = prob->Nf;
382: PetscBool hasH = PETSC_FALSE;
383: PetscInt dim, dimEmbed, NbMax = 0, NcMax = 0, NqMax = 0, NsMax = 1, f;
388: if (prob->setup) return(0);
389: /* Calculate sizes */
390: PetscDSGetSpatialDimension(prob, &dim);
391: PetscDSGetCoordinateDimension(prob, &dimEmbed);
392: prob->totDim = prob->totComp = 0;
393: PetscMalloc2(Nf,&prob->Nc,Nf,&prob->Nb);
394: PetscCalloc2(Nf+1,&prob->off,Nf+1,&prob->offDer);
395: PetscMalloc2(Nf,&prob->T,Nf,&prob->Tf);
396: for (f = 0; f < Nf; ++f) {
397: PetscObject obj;
398: PetscClassId id;
399: PetscQuadrature q = NULL;
400: PetscInt Nq = 0, Nb, Nc;
402: PetscDSGetDiscretization(prob, f, &obj);
403: if (prob->jetDegree[f] > 1) hasH = PETSC_TRUE;
404: if (!obj) {
405: /* Empty mesh */
406: Nb = Nc = 0;
407: prob->T[f] = prob->Tf[f] = NULL;
408: } else {
409: PetscObjectGetClassId(obj, &id);
410: if (id == PETSCFE_CLASSID) {
411: PetscFE fe = (PetscFE) obj;
413: PetscFEGetQuadrature(fe, &q);
414: PetscFEGetDimension(fe, &Nb);
415: PetscFEGetNumComponents(fe, &Nc);
416: PetscFEGetCellTabulation(fe, prob->jetDegree[f], &prob->T[f]);
417: PetscFEGetFaceTabulation(fe, prob->jetDegree[f], &prob->Tf[f]);
418: } else if (id == PETSCFV_CLASSID) {
419: PetscFV fv = (PetscFV) obj;
421: PetscFVGetQuadrature(fv, &q);
422: PetscFVGetNumComponents(fv, &Nc);
423: Nb = Nc;
424: PetscFVGetCellTabulation(fv, &prob->T[f]);
425: /* TODO: should PetscFV also have face tabulation? Otherwise there will be a null pointer in prob->basisFace */
426: } else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f);
427: }
428: prob->Nc[f] = Nc;
429: prob->Nb[f] = Nb;
430: prob->off[f+1] = Nc + prob->off[f];
431: prob->offDer[f+1] = Nc*dim + prob->offDer[f];
432: if (q) {PetscQuadratureGetData(q, NULL, NULL, &Nq, NULL, NULL);}
433: NqMax = PetscMax(NqMax, Nq);
434: NbMax = PetscMax(NbMax, Nb);
435: NcMax = PetscMax(NcMax, Nc);
436: prob->totDim += Nb;
437: prob->totComp += Nc;
438: /* There are two faces for all fields but the cohesive field on a hybrid cell */
439: if (prob->isHybrid && (f < Nf-1)) prob->totDim += Nb;
440: }
441: /* Allocate works space */
442: if (prob->isHybrid) NsMax = 2;
443: 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);
444: PetscMalloc5(dimEmbed,&prob->x,NbMax*NcMax,&prob->basisReal,NbMax*NcMax*dimEmbed,&prob->basisDerReal,NbMax*NcMax,&prob->testReal,NbMax*NcMax*dimEmbed,&prob->testDerReal);
445: PetscMalloc6(NsMax*NqMax*NcMax,&prob->f0,NsMax*NqMax*NcMax*dimEmbed,&prob->f1,
446: NsMax*NsMax*NqMax*NcMax*NcMax,&prob->g0,NsMax*NsMax*NqMax*NcMax*NcMax*dimEmbed,&prob->g1,
447: NsMax*NsMax*NqMax*NcMax*NcMax*dimEmbed,&prob->g2,NsMax*NsMax*NqMax*NcMax*NcMax*dimEmbed*dimEmbed,&prob->g3);
448: if (prob->ops->setup) {(*prob->ops->setup)(prob);}
449: prob->setup = PETSC_TRUE;
450: return(0);
451: }
453: static PetscErrorCode PetscDSDestroyStructs_Static(PetscDS prob)
454: {
458: PetscFree2(prob->Nc,prob->Nb);
459: PetscFree2(prob->off,prob->offDer);
460: PetscFree2(prob->T,prob->Tf);
461: PetscFree3(prob->u,prob->u_t,prob->u_x);
462: PetscFree5(prob->x,prob->basisReal, prob->basisDerReal,prob->testReal,prob->testDerReal);
463: PetscFree6(prob->f0,prob->f1,prob->g0,prob->g1,prob->g2,prob->g3);
464: return(0);
465: }
467: static PetscErrorCode PetscDSEnlarge_Static(PetscDS prob, PetscInt NfNew)
468: {
469: PetscObject *tmpd;
470: PetscBool *tmpi;
471: PetscInt *tmpk;
472: PetscPointFunc *tmpup;
473: PetscSimplePointFunc *tmpexactSol, *tmpexactSol_t;
474: void **tmpexactCtx, **tmpexactCtx_t;
475: void **tmpctx;
476: PetscInt Nf = prob->Nf, f;
477: PetscErrorCode ierr;
480: if (Nf >= NfNew) return(0);
481: prob->setup = PETSC_FALSE;
482: PetscDSDestroyStructs_Static(prob);
483: PetscMalloc3(NfNew, &tmpd, NfNew, &tmpi, NfNew, &tmpk);
484: for (f = 0; f < Nf; ++f) {tmpd[f] = prob->disc[f]; tmpi[f] = prob->implicit[f]; tmpk[f] = prob->jetDegree[f];}
485: for (f = Nf; f < NfNew; ++f) {tmpd[f] = NULL; tmpi[f] = PETSC_TRUE; tmpk[f] = 1;}
486: PetscFree3(prob->disc, prob->implicit, prob->jetDegree);
487: PetscWeakFormSetNumFields(prob->wf, NfNew);
488: prob->Nf = NfNew;
489: prob->disc = tmpd;
490: prob->implicit = tmpi;
491: prob->jetDegree = tmpk;
492: PetscCalloc2(NfNew, &tmpup, NfNew, &tmpctx);
493: for (f = 0; f < Nf; ++f) tmpup[f] = prob->update[f];
494: for (f = 0; f < Nf; ++f) tmpctx[f] = prob->ctx[f];
495: for (f = Nf; f < NfNew; ++f) tmpup[f] = NULL;
496: for (f = Nf; f < NfNew; ++f) tmpctx[f] = NULL;
497: PetscFree2(prob->update, prob->ctx);
498: prob->update = tmpup;
499: prob->ctx = tmpctx;
500: PetscCalloc4(NfNew, &tmpexactSol, NfNew, &tmpexactCtx, NfNew, &tmpexactSol_t, NfNew, &tmpexactCtx_t);
501: for (f = 0; f < Nf; ++f) tmpexactSol[f] = prob->exactSol[f];
502: for (f = 0; f < Nf; ++f) tmpexactCtx[f] = prob->exactCtx[f];
503: for (f = 0; f < Nf; ++f) tmpexactSol_t[f] = prob->exactSol_t[f];
504: for (f = 0; f < Nf; ++f) tmpexactCtx_t[f] = prob->exactCtx_t[f];
505: for (f = Nf; f < NfNew; ++f) tmpexactSol[f] = NULL;
506: for (f = Nf; f < NfNew; ++f) tmpexactCtx[f] = NULL;
507: for (f = Nf; f < NfNew; ++f) tmpexactSol_t[f] = NULL;
508: for (f = Nf; f < NfNew; ++f) tmpexactCtx_t[f] = NULL;
509: PetscFree4(prob->exactSol, prob->exactCtx, prob->exactSol_t, prob->exactCtx_t);
510: prob->exactSol = tmpexactSol;
511: prob->exactCtx = tmpexactCtx;
512: prob->exactSol_t = tmpexactSol_t;
513: prob->exactCtx_t = tmpexactCtx_t;
514: return(0);
515: }
517: /*@
518: PetscDSDestroy - Destroys a PetscDS object
520: Collective on prob
522: Input Parameter:
523: . prob - the PetscDS object to destroy
525: Level: developer
527: .seealso PetscDSView()
528: @*/
529: PetscErrorCode PetscDSDestroy(PetscDS *ds)
530: {
531: PetscInt f;
532: DSBoundary next;
536: if (!*ds) return(0);
539: if (--((PetscObject)(*ds))->refct > 0) {*ds = NULL; return(0);}
540: ((PetscObject) (*ds))->refct = 0;
541: if ((*ds)->subprobs) {
542: PetscInt dim, d;
544: PetscDSGetSpatialDimension(*ds, &dim);
545: for (d = 0; d < dim; ++d) {PetscDSDestroy(&(*ds)->subprobs[d]);}
546: }
547: PetscFree((*ds)->subprobs);
548: PetscDSDestroyStructs_Static(*ds);
549: for (f = 0; f < (*ds)->Nf; ++f) {
550: PetscObjectDereference((*ds)->disc[f]);
551: }
552: PetscFree3((*ds)->disc, (*ds)->implicit, (*ds)->jetDegree);
553: PetscWeakFormDestroy(&(*ds)->wf);
554: PetscFree2((*ds)->update,(*ds)->ctx);
555: PetscFree4((*ds)->exactSol,(*ds)->exactCtx,(*ds)->exactSol_t,(*ds)->exactCtx_t);
556: if ((*ds)->ops->destroy) {(*(*ds)->ops->destroy)(*ds);}
557: next = (*ds)->boundary;
558: while (next) {
559: DSBoundary b = next;
561: next = b->next;
562: PetscFree(b->comps);
563: PetscFree(b->ids);
564: PetscFree(b->name);
565: PetscFree(b->labelname);
566: PetscFree(b);
567: }
568: PetscFree((*ds)->constants);
569: PetscHeaderDestroy(ds);
570: return(0);
571: }
573: /*@
574: PetscDSCreate - Creates an empty PetscDS object. The type can then be set with PetscDSSetType().
576: Collective
578: Input Parameter:
579: . comm - The communicator for the PetscDS object
581: Output Parameter:
582: . ds - The PetscDS object
584: Level: beginner
586: .seealso: PetscDSSetType(), PETSCDSBASIC
587: @*/
588: PetscErrorCode PetscDSCreate(MPI_Comm comm, PetscDS *ds)
589: {
590: PetscDS p;
595: *ds = NULL;
596: PetscDSInitializePackage();
598: PetscHeaderCreate(p, PETSCDS_CLASSID, "PetscDS", "Discrete System", "PetscDS", comm, PetscDSDestroy, PetscDSView);
600: p->Nf = 0;
601: p->setup = PETSC_FALSE;
602: p->numConstants = 0;
603: p->constants = NULL;
604: p->dimEmbed = -1;
605: p->useJacPre = PETSC_TRUE;
606: PetscWeakFormCreate(comm, &p->wf);
608: *ds = p;
609: return(0);
610: }
612: /*@
613: PetscDSGetNumFields - Returns the number of fields in the DS
615: Not collective
617: Input Parameter:
618: . prob - The PetscDS object
620: Output Parameter:
621: . Nf - The number of fields
623: Level: beginner
625: .seealso: PetscDSGetSpatialDimension(), PetscDSCreate()
626: @*/
627: PetscErrorCode PetscDSGetNumFields(PetscDS prob, PetscInt *Nf)
628: {
632: *Nf = prob->Nf;
633: return(0);
634: }
636: /*@
637: PetscDSGetSpatialDimension - Returns the spatial dimension of the DS, meaning the topological dimension of the discretizations
639: Not collective
641: Input Parameter:
642: . prob - The PetscDS object
644: Output Parameter:
645: . dim - The spatial dimension
647: Level: beginner
649: .seealso: PetscDSGetCoordinateDimension(), PetscDSGetNumFields(), PetscDSCreate()
650: @*/
651: PetscErrorCode PetscDSGetSpatialDimension(PetscDS prob, PetscInt *dim)
652: {
658: *dim = 0;
659: if (prob->Nf) {
660: PetscObject obj;
661: PetscClassId id;
663: PetscDSGetDiscretization(prob, 0, &obj);
664: if (obj) {
665: PetscObjectGetClassId(obj, &id);
666: if (id == PETSCFE_CLASSID) {PetscFEGetSpatialDimension((PetscFE) obj, dim);}
667: else if (id == PETSCFV_CLASSID) {PetscFVGetSpatialDimension((PetscFV) obj, dim);}
668: else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
669: }
670: }
671: return(0);
672: }
674: /*@
675: PetscDSGetCoordinateDimension - Returns the coordinate dimension of the DS, meaning the dimension of the space into which the discretiaztions are embedded
677: Not collective
679: Input Parameter:
680: . prob - The PetscDS object
682: Output Parameter:
683: . dimEmbed - The coordinate dimension
685: Level: beginner
687: .seealso: PetscDSSetCoordinateDimension(), PetscDSGetSpatialDimension(), PetscDSGetNumFields(), PetscDSCreate()
688: @*/
689: PetscErrorCode PetscDSGetCoordinateDimension(PetscDS prob, PetscInt *dimEmbed)
690: {
694: if (prob->dimEmbed < 0) SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONGSTATE, "No coordinate dimension set for this DS");
695: *dimEmbed = prob->dimEmbed;
696: return(0);
697: }
699: /*@
700: PetscDSSetCoordinateDimension - Set the coordinate dimension of the DS, meaning the dimension of the space into which the discretiaztions are embedded
702: Logically collective on prob
704: Input Parameters:
705: + prob - The PetscDS object
706: - dimEmbed - The coordinate dimension
708: Level: beginner
710: .seealso: PetscDSGetCoordinateDimension(), PetscDSGetSpatialDimension(), PetscDSGetNumFields(), PetscDSCreate()
711: @*/
712: PetscErrorCode PetscDSSetCoordinateDimension(PetscDS prob, PetscInt dimEmbed)
713: {
716: if (dimEmbed < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate dimension must be non-negative, not %D", dimEmbed);
717: prob->dimEmbed = dimEmbed;
718: return(0);
719: }
721: /*@
722: PetscDSGetHybrid - Returns the flag for a hybrid (cohesive) cell
724: Not collective
726: Input Parameter:
727: . prob - The PetscDS object
729: Output Parameter:
730: . isHybrid - The flag
732: Level: developer
734: .seealso: PetscDSSetHybrid(), PetscDSCreate()
735: @*/
736: PetscErrorCode PetscDSGetHybrid(PetscDS prob, PetscBool *isHybrid)
737: {
741: *isHybrid = prob->isHybrid;
742: return(0);
743: }
745: /*@
746: PetscDSSetHybrid - Set the flag for a hybrid (cohesive) cell
748: Not collective
750: Input Parameters:
751: + prob - The PetscDS object
752: - isHybrid - The flag
754: Level: developer
756: .seealso: PetscDSGetHybrid(), PetscDSCreate()
757: @*/
758: PetscErrorCode PetscDSSetHybrid(PetscDS prob, PetscBool isHybrid)
759: {
762: prob->isHybrid = isHybrid;
763: return(0);
764: }
766: /*@
767: PetscDSGetTotalDimension - Returns the total size of the approximation space for this system
769: Not collective
771: Input Parameter:
772: . prob - The PetscDS object
774: Output Parameter:
775: . dim - The total problem dimension
777: Level: beginner
779: .seealso: PetscDSGetNumFields(), PetscDSCreate()
780: @*/
781: PetscErrorCode PetscDSGetTotalDimension(PetscDS prob, PetscInt *dim)
782: {
787: PetscDSSetUp(prob);
789: *dim = prob->totDim;
790: return(0);
791: }
793: /*@
794: PetscDSGetTotalComponents - Returns the total number of components in this system
796: Not collective
798: Input Parameter:
799: . prob - The PetscDS object
801: Output Parameter:
802: . dim - The total number of components
804: Level: beginner
806: .seealso: PetscDSGetNumFields(), PetscDSCreate()
807: @*/
808: PetscErrorCode PetscDSGetTotalComponents(PetscDS prob, PetscInt *Nc)
809: {
814: PetscDSSetUp(prob);
816: *Nc = prob->totComp;
817: return(0);
818: }
820: /*@
821: PetscDSGetDiscretization - Returns the discretization object for the given field
823: Not collective
825: Input Parameters:
826: + prob - The PetscDS object
827: - f - The field number
829: Output Parameter:
830: . disc - The discretization object
832: Level: beginner
834: .seealso: PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
835: @*/
836: PetscErrorCode PetscDSGetDiscretization(PetscDS prob, PetscInt f, PetscObject *disc)
837: {
841: 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);
842: *disc = prob->disc[f];
843: return(0);
844: }
846: /*@
847: PetscDSSetDiscretization - Sets the discretization object for the given field
849: Not collective
851: Input Parameters:
852: + prob - The PetscDS object
853: . f - The field number
854: - disc - The discretization object
856: Level: beginner
858: .seealso: PetscDSGetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
859: @*/
860: PetscErrorCode PetscDSSetDiscretization(PetscDS prob, PetscInt f, PetscObject disc)
861: {
867: if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
868: PetscDSEnlarge_Static(prob, f+1);
869: PetscObjectDereference(prob->disc[f]);
870: prob->disc[f] = disc;
871: PetscObjectReference(disc);
872: if (disc) {
873: PetscClassId id;
875: PetscObjectGetClassId(disc, &id);
876: if (id == PETSCFE_CLASSID) {
877: PetscDSSetImplicit(prob, f, PETSC_TRUE);
878: } else if (id == PETSCFV_CLASSID) {
879: PetscDSSetImplicit(prob, f, PETSC_FALSE);
880: }
881: PetscDSSetJetDegree(prob, f, 1);
882: }
883: return(0);
884: }
886: /*@
887: PetscDSGetWeakForm - Returns the weak form object
889: Not collective
891: Input Parameter:
892: . ds - The PetscDS object
894: Output Parameter:
895: . wf - The weak form object
897: Level: beginner
899: .seealso: PetscDSSetWeakForm(), PetscDSGetNumFields(), PetscDSCreate()
900: @*/
901: PetscErrorCode PetscDSGetWeakForm(PetscDS ds, PetscWeakForm *wf)
902: {
906: *wf = ds->wf;
907: return(0);
908: }
910: /*@
911: PetscDSSetWeakForm - Sets the weak form object
913: Not collective
915: Input Parameters:
916: + ds - The PetscDS object
917: - wf - The weak form object
919: Level: beginner
921: .seealso: PetscDSGetWeakForm(), PetscDSGetNumFields(), PetscDSCreate()
922: @*/
923: PetscErrorCode PetscDSSetWeakForm(PetscDS ds, PetscWeakForm wf)
924: {
930: PetscObjectDereference((PetscObject) ds->wf);
931: ds->wf = wf;
932: PetscObjectReference((PetscObject) wf);
933: PetscWeakFormSetNumFields(wf, ds->Nf);
934: return(0);
935: }
937: /*@
938: PetscDSAddDiscretization - Adds a discretization object
940: Not collective
942: Input Parameters:
943: + prob - The PetscDS object
944: - disc - The boundary discretization object
946: Level: beginner
948: .seealso: PetscDSGetDiscretization(), PetscDSSetDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
949: @*/
950: PetscErrorCode PetscDSAddDiscretization(PetscDS prob, PetscObject disc)
951: {
955: PetscDSSetDiscretization(prob, prob->Nf, disc);
956: return(0);
957: }
959: /*@
960: PetscDSGetQuadrature - Returns the quadrature, which must agree for all fields in the DS
962: Not collective
964: Input Parameter:
965: . prob - The PetscDS object
967: Output Parameter:
968: . q - The quadrature object
970: Level: intermediate
972: .seealso: PetscDSSetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
973: @*/
974: PetscErrorCode PetscDSGetQuadrature(PetscDS prob, PetscQuadrature *q)
975: {
976: PetscObject obj;
977: PetscClassId id;
981: *q = NULL;
982: if (!prob->Nf) return(0);
983: PetscDSGetDiscretization(prob, 0, &obj);
984: PetscObjectGetClassId(obj, &id);
985: if (id == PETSCFE_CLASSID) {PetscFEGetQuadrature((PetscFE) obj, q);}
986: else if (id == PETSCFV_CLASSID) {PetscFVGetQuadrature((PetscFV) obj, q);}
987: else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
988: return(0);
989: }
991: /*@
992: PetscDSGetImplicit - Returns the flag for implicit solve for this field. This is just a guide for IMEX
994: Not collective
996: Input Parameters:
997: + prob - The PetscDS object
998: - f - The field number
1000: Output Parameter:
1001: . implicit - The flag indicating what kind of solve to use for this field
1003: Level: developer
1005: .seealso: PetscDSSetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
1006: @*/
1007: PetscErrorCode PetscDSGetImplicit(PetscDS prob, PetscInt f, PetscBool *implicit)
1008: {
1012: 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);
1013: *implicit = prob->implicit[f];
1014: return(0);
1015: }
1017: /*@
1018: PetscDSSetImplicit - Set the flag for implicit solve for this field. This is just a guide for IMEX
1020: Not collective
1022: Input Parameters:
1023: + prob - The PetscDS object
1024: . f - The field number
1025: - implicit - The flag indicating what kind of solve to use for this field
1027: Level: developer
1029: .seealso: PetscDSGetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
1030: @*/
1031: PetscErrorCode PetscDSSetImplicit(PetscDS prob, PetscInt f, PetscBool implicit)
1032: {
1035: 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);
1036: prob->implicit[f] = implicit;
1037: return(0);
1038: }
1040: /*@
1041: PetscDSGetJetDegree - Returns the highest derivative for this field equation, or the k-jet that the discretization needs to tabulate.
1043: Not collective
1045: Input Parameters:
1046: + ds - The PetscDS object
1047: - f - The field number
1049: Output Parameter:
1050: . k - The highest derivative we need to tabulate
1052: Level: developer
1054: .seealso: PetscDSSetJetDegree(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
1055: @*/
1056: PetscErrorCode PetscDSGetJetDegree(PetscDS ds, PetscInt f, PetscInt *k)
1057: {
1061: 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);
1062: *k = ds->jetDegree[f];
1063: return(0);
1064: }
1066: /*@
1067: PetscDSSetJetDegree - Set the highest derivative for this field equation, or the k-jet that the discretization needs to tabulate.
1069: Not collective
1071: Input Parameters:
1072: + ds - The PetscDS object
1073: . f - The field number
1074: - k - The highest derivative we need to tabulate
1076: Level: developer
1078: .seealso: PetscDSGetJetDegree(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
1079: @*/
1080: PetscErrorCode PetscDSSetJetDegree(PetscDS ds, PetscInt f, PetscInt k)
1081: {
1084: 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);
1085: ds->jetDegree[f] = k;
1086: return(0);
1087: }
1089: PetscErrorCode PetscDSGetObjective(PetscDS ds, PetscInt f,
1090: void (**obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1091: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1092: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1093: PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]))
1094: {
1095: PetscPointFunc *tmp;
1096: PetscInt n;
1097: PetscErrorCode ierr;
1102: 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);
1103: PetscWeakFormGetObjective(ds->wf, NULL, 0, f, &n, &tmp);
1104: *obj = tmp ? tmp[0] : NULL;
1105: return(0);
1106: }
1108: PetscErrorCode PetscDSSetObjective(PetscDS ds, PetscInt f,
1109: void (*obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1110: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1111: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1112: PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]))
1113: {
1119: if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1120: PetscWeakFormSetIndexObjective(ds->wf, NULL, 0, f, 0, obj);
1121: return(0);
1122: }
1124: /*@C
1125: PetscDSGetResidual - Get the pointwise residual function for a given test field
1127: Not collective
1129: Input Parameters:
1130: + ds - The PetscDS
1131: - f - The test field number
1133: Output Parameters:
1134: + f0 - integrand for the test function term
1135: - f1 - integrand for the test function gradient term
1137: Note: We are using a first order FEM model for the weak form:
1139: \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)
1141: The calling sequence for the callbacks f0 and f1 is given by:
1143: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1144: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1145: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1146: $ PetscReal t, const PetscReal x[], PetscScalar f0[])
1148: + dim - the spatial dimension
1149: . Nf - the number of fields
1150: . uOff - the offset into u[] and u_t[] for each field
1151: . uOff_x - the offset into u_x[] for each field
1152: . u - each field evaluated at the current point
1153: . u_t - the time derivative of each field evaluated at the current point
1154: . u_x - the gradient of each field evaluated at the current point
1155: . aOff - the offset into a[] and a_t[] for each auxiliary field
1156: . aOff_x - the offset into a_x[] for each auxiliary field
1157: . a - each auxiliary field evaluated at the current point
1158: . a_t - the time derivative of each auxiliary field evaluated at the current point
1159: . a_x - the gradient of auxiliary each field evaluated at the current point
1160: . t - current time
1161: . x - coordinates of the current point
1162: . numConstants - number of constant parameters
1163: . constants - constant parameters
1164: - f0 - output values at the current point
1166: Level: intermediate
1168: .seealso: PetscDSSetResidual()
1169: @*/
1170: PetscErrorCode PetscDSGetResidual(PetscDS ds, PetscInt f,
1171: void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1172: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1173: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1174: PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
1175: void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1176: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1177: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1178: PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
1179: {
1180: PetscPointFunc *tmp0, *tmp1;
1181: PetscInt n0, n1;
1182: PetscErrorCode ierr;
1186: 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);
1187: PetscWeakFormGetResidual(ds->wf, NULL, 0, f, &n0, &tmp0, &n1, &tmp1);
1188: *f0 = tmp0 ? tmp0[0] : NULL;
1189: *f1 = tmp1 ? tmp1[0] : NULL;
1190: return(0);
1191: }
1193: /*@C
1194: PetscDSSetResidual - Set the pointwise residual function for a given test field
1196: Not collective
1198: Input Parameters:
1199: + ds - The PetscDS
1200: . f - The test field number
1201: . f0 - integrand for the test function term
1202: - f1 - integrand for the test function gradient term
1204: Note: We are using a first order FEM model for the weak form:
1206: \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)
1208: The calling sequence for the callbacks f0 and f1 is given by:
1210: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1211: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1212: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1213: $ PetscReal t, const PetscReal x[], PetscScalar f0[])
1215: + dim - the spatial dimension
1216: . Nf - the number of fields
1217: . uOff - the offset into u[] and u_t[] for each field
1218: . uOff_x - the offset into u_x[] for each field
1219: . u - each field evaluated at the current point
1220: . u_t - the time derivative of each field evaluated at the current point
1221: . u_x - the gradient of each field evaluated at the current point
1222: . aOff - the offset into a[] and a_t[] for each auxiliary field
1223: . aOff_x - the offset into a_x[] for each auxiliary field
1224: . a - each auxiliary field evaluated at the current point
1225: . a_t - the time derivative of each auxiliary field evaluated at the current point
1226: . a_x - the gradient of auxiliary each field evaluated at the current point
1227: . t - current time
1228: . x - coordinates of the current point
1229: . numConstants - number of constant parameters
1230: . constants - constant parameters
1231: - f0 - output values at the current point
1233: Level: intermediate
1235: .seealso: PetscDSGetResidual()
1236: @*/
1237: PetscErrorCode PetscDSSetResidual(PetscDS ds, PetscInt f,
1238: void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1239: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1240: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1241: PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
1242: void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1243: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1244: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1245: PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
1246: {
1253: if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1254: PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 0, f0, 0, f1);
1255: return(0);
1256: }
1258: /*@C
1259: PetscDSHasJacobian - Signals that Jacobian functions have been set
1261: Not collective
1263: Input Parameter:
1264: . prob - The PetscDS
1266: Output Parameter:
1267: . hasJac - flag that pointwise function for the Jacobian has been set
1269: Level: intermediate
1271: .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
1272: @*/
1273: PetscErrorCode PetscDSHasJacobian(PetscDS ds, PetscBool *hasJac)
1274: {
1279: PetscWeakFormHasJacobian(ds->wf, hasJac);
1280: return(0);
1281: }
1283: /*@C
1284: PetscDSGetJacobian - Get the pointwise Jacobian function for given test and basis field
1286: Not collective
1288: Input Parameters:
1289: + ds - The PetscDS
1290: . f - The test field number
1291: - g - The field number
1293: Output Parameters:
1294: + g0 - integrand for the test and basis function term
1295: . g1 - integrand for the test function and basis function gradient term
1296: . g2 - integrand for the test function gradient and basis function term
1297: - g3 - integrand for the test function gradient and basis function gradient term
1299: Note: We are using a first order FEM model for the weak form:
1301: \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
1303: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
1305: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1306: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1307: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1308: $ PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])
1310: + dim - the spatial dimension
1311: . Nf - the number of fields
1312: . uOff - the offset into u[] and u_t[] for each field
1313: . uOff_x - the offset into u_x[] for each field
1314: . u - each field evaluated at the current point
1315: . u_t - the time derivative of each field evaluated at the current point
1316: . u_x - the gradient of each field evaluated at the current point
1317: . aOff - the offset into a[] and a_t[] for each auxiliary field
1318: . aOff_x - the offset into a_x[] for each auxiliary field
1319: . a - each auxiliary field evaluated at the current point
1320: . a_t - the time derivative of each auxiliary field evaluated at the current point
1321: . a_x - the gradient of auxiliary each field evaluated at the current point
1322: . t - current time
1323: . u_tShift - the multiplier a for dF/dU_t
1324: . x - coordinates of the current point
1325: . numConstants - number of constant parameters
1326: . constants - constant parameters
1327: - g0 - output values at the current point
1329: Level: intermediate
1331: .seealso: PetscDSSetJacobian()
1332: @*/
1333: PetscErrorCode PetscDSGetJacobian(PetscDS ds, PetscInt f, PetscInt g,
1334: void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1335: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1336: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1337: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1338: void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1339: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1340: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1341: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1342: void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1343: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1344: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1345: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1346: void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1347: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1348: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1349: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1350: {
1351: PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
1352: PetscInt n0, n1, n2, n3;
1357: 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);
1358: 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);
1359: PetscWeakFormGetJacobian(ds->wf, NULL, 0, f, g, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);
1360: *g0 = tmp0 ? tmp0[0] : NULL;
1361: *g1 = tmp1 ? tmp1[0] : NULL;
1362: *g2 = tmp2 ? tmp2[0] : NULL;
1363: *g3 = tmp3 ? tmp3[0] : NULL;
1364: return(0);
1365: }
1367: /*@C
1368: PetscDSSetJacobian - Set the pointwise Jacobian function for given test and basis fields
1370: Not collective
1372: Input Parameters:
1373: + ds - The PetscDS
1374: . f - The test field number
1375: . g - The field number
1376: . g0 - integrand for the test and basis function term
1377: . g1 - integrand for the test function and basis function gradient term
1378: . g2 - integrand for the test function gradient and basis function term
1379: - g3 - integrand for the test function gradient and basis function gradient term
1381: Note: We are using a first order FEM model for the weak form:
1383: \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
1385: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
1387: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1388: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1389: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1390: $ PetscReal t, const PetscReal x[], PetscScalar g0[])
1392: + dim - the spatial dimension
1393: . Nf - the number of fields
1394: . uOff - the offset into u[] and u_t[] for each field
1395: . uOff_x - the offset into u_x[] for each field
1396: . u - each field evaluated at the current point
1397: . u_t - the time derivative of each field evaluated at the current point
1398: . u_x - the gradient of each field evaluated at the current point
1399: . aOff - the offset into a[] and a_t[] for each auxiliary field
1400: . aOff_x - the offset into a_x[] for each auxiliary field
1401: . a - each auxiliary field evaluated at the current point
1402: . a_t - the time derivative of each auxiliary field evaluated at the current point
1403: . a_x - the gradient of auxiliary each field evaluated at the current point
1404: . t - current time
1405: . u_tShift - the multiplier a for dF/dU_t
1406: . x - coordinates of the current point
1407: . numConstants - number of constant parameters
1408: . constants - constant parameters
1409: - g0 - output values at the current point
1411: Level: intermediate
1413: .seealso: PetscDSGetJacobian()
1414: @*/
1415: PetscErrorCode PetscDSSetJacobian(PetscDS ds, PetscInt f, PetscInt g,
1416: void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1417: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1418: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1419: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1420: void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1421: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1422: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1423: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1424: void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1425: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1426: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1427: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1428: void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1429: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1430: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1431: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1432: {
1441: if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1442: if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
1443: PetscWeakFormSetIndexJacobian(ds->wf, NULL, 0, f, g, 0, g0, 0, g1, 0, g2, 0, g3);
1444: return(0);
1445: }
1447: /*@C
1448: PetscDSUseJacobianPreconditioner - Whether to construct a Jacobian preconditioner
1450: Not collective
1452: Input Parameters:
1453: + prob - The PetscDS
1454: - useJacPre - flag that enables construction of a Jacobian preconditioner
1456: Level: intermediate
1458: .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
1459: @*/
1460: PetscErrorCode PetscDSUseJacobianPreconditioner(PetscDS prob, PetscBool useJacPre)
1461: {
1464: prob->useJacPre = useJacPre;
1465: return(0);
1466: }
1468: /*@C
1469: PetscDSHasJacobianPreconditioner - Signals that a Jacobian preconditioner matrix has been set
1471: Not collective
1473: Input Parameter:
1474: . prob - The PetscDS
1476: Output Parameter:
1477: . hasJacPre - flag that pointwise function for Jacobian preconditioner matrix has been set
1479: Level: intermediate
1481: .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
1482: @*/
1483: PetscErrorCode PetscDSHasJacobianPreconditioner(PetscDS ds, PetscBool *hasJacPre)
1484: {
1489: *hasJacPre = PETSC_FALSE;
1490: if (!ds->useJacPre) return(0);
1491: PetscWeakFormHasJacobianPreconditioner(ds->wf, hasJacPre);
1492: return(0);
1493: }
1495: /*@C
1496: 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.
1498: Not collective
1500: Input Parameters:
1501: + ds - The PetscDS
1502: . f - The test field number
1503: - g - The field number
1505: Output Parameters:
1506: + g0 - integrand for the test and basis function term
1507: . g1 - integrand for the test function and basis function gradient term
1508: . g2 - integrand for the test function gradient and basis function term
1509: - g3 - integrand for the test function gradient and basis function gradient term
1511: Note: We are using a first order FEM model for the weak form:
1513: \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
1515: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
1517: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1518: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1519: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1520: $ PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])
1522: + dim - the spatial dimension
1523: . Nf - the number of fields
1524: . uOff - the offset into u[] and u_t[] for each field
1525: . uOff_x - the offset into u_x[] for each field
1526: . u - each field evaluated at the current point
1527: . u_t - the time derivative of each field evaluated at the current point
1528: . u_x - the gradient of each field evaluated at the current point
1529: . aOff - the offset into a[] and a_t[] for each auxiliary field
1530: . aOff_x - the offset into a_x[] for each auxiliary field
1531: . a - each auxiliary field evaluated at the current point
1532: . a_t - the time derivative of each auxiliary field evaluated at the current point
1533: . a_x - the gradient of auxiliary each field evaluated at the current point
1534: . t - current time
1535: . u_tShift - the multiplier a for dF/dU_t
1536: . x - coordinates of the current point
1537: . numConstants - number of constant parameters
1538: . constants - constant parameters
1539: - g0 - output values at the current point
1541: Level: intermediate
1543: .seealso: PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian()
1544: @*/
1545: PetscErrorCode PetscDSGetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g,
1546: void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1547: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1548: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1549: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1550: void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1551: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1552: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1553: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1554: void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1555: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1556: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1557: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1558: void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1559: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1560: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1561: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1562: {
1563: PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
1564: PetscInt n0, n1, n2, n3;
1569: 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);
1570: 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);
1571: PetscWeakFormGetJacobianPreconditioner(ds->wf, NULL, 0, f, g, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);
1572: *g0 = tmp0 ? tmp0[0] : NULL;
1573: *g1 = tmp1 ? tmp1[0] : NULL;
1574: *g2 = tmp2 ? tmp2[0] : NULL;
1575: *g3 = tmp3 ? tmp3[0] : NULL;
1576: return(0);
1577: }
1579: /*@C
1580: 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.
1582: Not collective
1584: Input Parameters:
1585: + ds - The PetscDS
1586: . f - The test field number
1587: . g - The field number
1588: . g0 - integrand for the test and basis function term
1589: . g1 - integrand for the test function and basis function gradient term
1590: . g2 - integrand for the test function gradient and basis function term
1591: - g3 - integrand for the test function gradient and basis function gradient term
1593: Note: We are using a first order FEM model for the weak form:
1595: \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
1597: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
1599: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1600: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1601: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1602: $ PetscReal t, const PetscReal x[], PetscScalar g0[])
1604: + dim - the spatial dimension
1605: . Nf - the number of fields
1606: . uOff - the offset into u[] and u_t[] for each field
1607: . uOff_x - the offset into u_x[] for each field
1608: . u - each field evaluated at the current point
1609: . u_t - the time derivative of each field evaluated at the current point
1610: . u_x - the gradient of each field evaluated at the current point
1611: . aOff - the offset into a[] and a_t[] for each auxiliary field
1612: . aOff_x - the offset into a_x[] for each auxiliary field
1613: . a - each auxiliary field evaluated at the current point
1614: . a_t - the time derivative of each auxiliary field evaluated at the current point
1615: . a_x - the gradient of auxiliary each field evaluated at the current point
1616: . t - current time
1617: . u_tShift - the multiplier a for dF/dU_t
1618: . x - coordinates of the current point
1619: . numConstants - number of constant parameters
1620: . constants - constant parameters
1621: - g0 - output values at the current point
1623: Level: intermediate
1625: .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobian()
1626: @*/
1627: PetscErrorCode PetscDSSetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g,
1628: void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1629: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1630: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1631: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1632: void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1633: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1634: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1635: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1636: void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1637: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1638: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1639: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1640: void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1641: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1642: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1643: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1644: {
1653: if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1654: if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
1655: PetscWeakFormSetIndexJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, g0, 0, g1, 0, g2, 0, g3);
1656: return(0);
1657: }
1659: /*@C
1660: PetscDSHasDynamicJacobian - Signals that a dynamic Jacobian, dF/du_t, has been set
1662: Not collective
1664: Input Parameter:
1665: . ds - The PetscDS
1667: Output Parameter:
1668: . hasDynJac - flag that pointwise function for dynamic Jacobian has been set
1670: Level: intermediate
1672: .seealso: PetscDSGetDynamicJacobian(), PetscDSSetDynamicJacobian(), PetscDSGetJacobian()
1673: @*/
1674: PetscErrorCode PetscDSHasDynamicJacobian(PetscDS ds, PetscBool *hasDynJac)
1675: {
1680: PetscWeakFormHasDynamicJacobian(ds->wf, hasDynJac);
1681: return(0);
1682: }
1684: /*@C
1685: PetscDSGetDynamicJacobian - Get the pointwise dynamic Jacobian, dF/du_t, function for given test and basis field
1687: Not collective
1689: Input Parameters:
1690: + ds - The PetscDS
1691: . f - The test field number
1692: - g - The field number
1694: Output Parameters:
1695: + g0 - integrand for the test and basis function term
1696: . g1 - integrand for the test function and basis function gradient term
1697: . g2 - integrand for the test function gradient and basis function term
1698: - g3 - integrand for the test function gradient and basis function gradient term
1700: Note: We are using a first order FEM model for the weak form:
1702: \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
1704: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
1706: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1707: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1708: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1709: $ PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])
1711: + dim - the spatial dimension
1712: . Nf - the number of fields
1713: . uOff - the offset into u[] and u_t[] for each field
1714: . uOff_x - the offset into u_x[] for each field
1715: . u - each field evaluated at the current point
1716: . u_t - the time derivative of each field evaluated at the current point
1717: . u_x - the gradient of each field evaluated at the current point
1718: . aOff - the offset into a[] and a_t[] for each auxiliary field
1719: . aOff_x - the offset into a_x[] for each auxiliary field
1720: . a - each auxiliary field evaluated at the current point
1721: . a_t - the time derivative of each auxiliary field evaluated at the current point
1722: . a_x - the gradient of auxiliary each field evaluated at the current point
1723: . t - current time
1724: . u_tShift - the multiplier a for dF/dU_t
1725: . x - coordinates of the current point
1726: . numConstants - number of constant parameters
1727: . constants - constant parameters
1728: - g0 - output values at the current point
1730: Level: intermediate
1732: .seealso: PetscDSSetJacobian()
1733: @*/
1734: PetscErrorCode PetscDSGetDynamicJacobian(PetscDS ds, PetscInt f, PetscInt g,
1735: void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1736: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1737: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1738: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1739: void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1740: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1741: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1742: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1743: void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1744: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1745: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1746: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1747: void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1748: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1749: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1750: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1751: {
1752: PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
1753: PetscInt n0, n1, n2, n3;
1758: 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);
1759: 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);
1760: PetscWeakFormGetDynamicJacobian(ds->wf, NULL, 0, f, g, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);
1761: *g0 = tmp0 ? tmp0[0] : NULL;
1762: *g1 = tmp1 ? tmp1[0] : NULL;
1763: *g2 = tmp2 ? tmp2[0] : NULL;
1764: *g3 = tmp3 ? tmp3[0] : NULL;
1765: return(0);
1766: }
1768: /*@C
1769: PetscDSSetDynamicJacobian - Set the pointwise dynamic Jacobian, dF/du_t, function for given test and basis fields
1771: Not collective
1773: Input Parameters:
1774: + ds - The PetscDS
1775: . f - The test field number
1776: . g - The field number
1777: . g0 - integrand for the test and basis function term
1778: . g1 - integrand for the test function and basis function gradient term
1779: . g2 - integrand for the test function gradient and basis function term
1780: - g3 - integrand for the test function gradient and basis function gradient term
1782: Note: We are using a first order FEM model for the weak form:
1784: \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
1786: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
1788: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1789: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1790: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1791: $ PetscReal t, const PetscReal x[], PetscScalar g0[])
1793: + dim - the spatial dimension
1794: . Nf - the number of fields
1795: . uOff - the offset into u[] and u_t[] for each field
1796: . uOff_x - the offset into u_x[] for each field
1797: . u - each field evaluated at the current point
1798: . u_t - the time derivative of each field evaluated at the current point
1799: . u_x - the gradient of each field evaluated at the current point
1800: . aOff - the offset into a[] and a_t[] for each auxiliary field
1801: . aOff_x - the offset into a_x[] for each auxiliary field
1802: . a - each auxiliary field evaluated at the current point
1803: . a_t - the time derivative of each auxiliary field evaluated at the current point
1804: . a_x - the gradient of auxiliary each field evaluated at the current point
1805: . t - current time
1806: . u_tShift - the multiplier a for dF/dU_t
1807: . x - coordinates of the current point
1808: . numConstants - number of constant parameters
1809: . constants - constant parameters
1810: - g0 - output values at the current point
1812: Level: intermediate
1814: .seealso: PetscDSGetJacobian()
1815: @*/
1816: PetscErrorCode PetscDSSetDynamicJacobian(PetscDS ds, PetscInt f, PetscInt g,
1817: void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1818: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1819: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1820: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
1821: void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1822: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1823: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1824: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
1825: void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1826: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1827: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1828: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
1829: void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1830: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1831: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1832: PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1833: {
1842: if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1843: if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
1844: PetscWeakFormSetIndexDynamicJacobian(ds->wf, NULL, 0, f, g, 0, g0, 0, g1, 0, g2, 0, g3);
1845: return(0);
1846: }
1848: /*@C
1849: PetscDSGetRiemannSolver - Returns the Riemann solver for the given field
1851: Not collective
1853: Input Arguments:
1854: + ds - The PetscDS object
1855: - f - The field number
1857: Output Argument:
1858: . r - Riemann solver
1860: Calling sequence for r:
1862: $ r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx)
1864: + dim - The spatial dimension
1865: . Nf - The number of fields
1866: . x - The coordinates at a point on the interface
1867: . n - The normal vector to the interface
1868: . uL - The state vector to the left of the interface
1869: . uR - The state vector to the right of the interface
1870: . flux - output array of flux through the interface
1871: . numConstants - number of constant parameters
1872: . constants - constant parameters
1873: - ctx - optional user context
1875: Level: intermediate
1877: .seealso: PetscDSSetRiemannSolver()
1878: @*/
1879: PetscErrorCode PetscDSGetRiemannSolver(PetscDS ds, PetscInt f,
1880: 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))
1881: {
1882: PetscRiemannFunc *tmp;
1883: PetscInt n;
1884: PetscErrorCode ierr;
1889: 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);
1890: PetscWeakFormGetRiemannSolver(ds->wf, NULL, 0, f, &n, &tmp);
1891: *r = tmp ? tmp[0] : NULL;
1892: return(0);
1893: }
1895: /*@C
1896: PetscDSSetRiemannSolver - Sets the Riemann solver for the given field
1898: Not collective
1900: Input Arguments:
1901: + ds - The PetscDS object
1902: . f - The field number
1903: - r - Riemann solver
1905: Calling sequence for r:
1907: $ r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx)
1909: + dim - The spatial dimension
1910: . Nf - The number of fields
1911: . x - The coordinates at a point on the interface
1912: . n - The normal vector to the interface
1913: . uL - The state vector to the left of the interface
1914: . uR - The state vector to the right of the interface
1915: . flux - output array of flux through the interface
1916: . numConstants - number of constant parameters
1917: . constants - constant parameters
1918: - ctx - optional user context
1920: Level: intermediate
1922: .seealso: PetscDSGetRiemannSolver()
1923: @*/
1924: PetscErrorCode PetscDSSetRiemannSolver(PetscDS ds, PetscInt f,
1925: 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))
1926: {
1932: if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
1933: PetscWeakFormSetIndexRiemannSolver(ds->wf, NULL, 0, f, 0, r);
1934: return(0);
1935: }
1937: /*@C
1938: PetscDSGetUpdate - Get the pointwise update function for a given field
1940: Not collective
1942: Input Parameters:
1943: + ds - The PetscDS
1944: - f - The field number
1946: Output Parameters:
1947: . update - update function
1949: Note: The calling sequence for the callback update is given by:
1951: $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1952: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1953: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1954: $ PetscReal t, const PetscReal x[], PetscScalar uNew[])
1956: + dim - the spatial dimension
1957: . Nf - the number of fields
1958: . uOff - the offset into u[] and u_t[] for each field
1959: . uOff_x - the offset into u_x[] for each field
1960: . u - each field evaluated at the current point
1961: . u_t - the time derivative of each field evaluated at the current point
1962: . u_x - the gradient of each field evaluated at the current point
1963: . aOff - the offset into a[] and a_t[] for each auxiliary field
1964: . aOff_x - the offset into a_x[] for each auxiliary field
1965: . a - each auxiliary field evaluated at the current point
1966: . a_t - the time derivative of each auxiliary field evaluated at the current point
1967: . a_x - the gradient of auxiliary each field evaluated at the current point
1968: . t - current time
1969: . x - coordinates of the current point
1970: - uNew - new value for field at the current point
1972: Level: intermediate
1974: .seealso: PetscDSSetUpdate(), PetscDSSetResidual()
1975: @*/
1976: PetscErrorCode PetscDSGetUpdate(PetscDS ds, PetscInt f,
1977: void (**update)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1978: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1979: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1980: PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[]))
1981: {
1984: 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);
1986: return(0);
1987: }
1989: /*@C
1990: PetscDSSetUpdate - Set the pointwise update function for a given field
1992: Not collective
1994: Input Parameters:
1995: + ds - The PetscDS
1996: . f - The field number
1997: - update - update function
1999: Note: The calling sequence for the callback update is given by:
2001: $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2002: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2003: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2004: $ PetscReal t, const PetscReal x[], PetscScalar uNew[])
2006: + dim - the spatial dimension
2007: . Nf - the number of fields
2008: . uOff - the offset into u[] and u_t[] for each field
2009: . uOff_x - the offset into u_x[] for each field
2010: . u - each field evaluated at the current point
2011: . u_t - the time derivative of each field evaluated at the current point
2012: . u_x - the gradient of each field evaluated at the current point
2013: . aOff - the offset into a[] and a_t[] for each auxiliary field
2014: . aOff_x - the offset into a_x[] for each auxiliary field
2015: . a - each auxiliary field evaluated at the current point
2016: . a_t - the time derivative of each auxiliary field evaluated at the current point
2017: . a_x - the gradient of auxiliary each field evaluated at the current point
2018: . t - current time
2019: . x - coordinates of the current point
2020: - uNew - new field values at the current point
2022: Level: intermediate
2024: .seealso: PetscDSGetResidual()
2025: @*/
2026: PetscErrorCode PetscDSSetUpdate(PetscDS ds, PetscInt f,
2027: void (*update)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2028: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2029: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2030: PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[]))
2031: {
2037: if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
2038: PetscDSEnlarge_Static(ds, f+1);
2039: ds->update[f] = update;
2040: return(0);
2041: }
2043: PetscErrorCode PetscDSGetContext(PetscDS ds, PetscInt f, void **ctx)
2044: {
2047: 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);
2049: *ctx = ds->ctx[f];
2050: return(0);
2051: }
2053: PetscErrorCode PetscDSSetContext(PetscDS ds, PetscInt f, void *ctx)
2054: {
2059: if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
2060: PetscDSEnlarge_Static(ds, f+1);
2061: ds->ctx[f] = ctx;
2062: return(0);
2063: }
2065: /*@C
2066: PetscDSGetBdResidual - Get the pointwise boundary residual function for a given test field
2068: Not collective
2070: Input Parameters:
2071: + ds - The PetscDS
2072: - f - The test field number
2074: Output Parameters:
2075: + f0 - boundary integrand for the test function term
2076: - f1 - boundary integrand for the test function gradient term
2078: Note: We are using a first order FEM model for the weak form:
2080: \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
2082: The calling sequence for the callbacks f0 and f1 is given by:
2084: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2085: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2086: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2087: $ PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])
2089: + dim - the spatial dimension
2090: . Nf - the number of fields
2091: . uOff - the offset into u[] and u_t[] for each field
2092: . uOff_x - the offset into u_x[] for each field
2093: . u - each field evaluated at the current point
2094: . u_t - the time derivative of each field evaluated at the current point
2095: . u_x - the gradient of each field evaluated at the current point
2096: . aOff - the offset into a[] and a_t[] for each auxiliary field
2097: . aOff_x - the offset into a_x[] for each auxiliary field
2098: . a - each auxiliary field evaluated at the current point
2099: . a_t - the time derivative of each auxiliary field evaluated at the current point
2100: . a_x - the gradient of auxiliary each field evaluated at the current point
2101: . t - current time
2102: . x - coordinates of the current point
2103: . n - unit normal at the current point
2104: . numConstants - number of constant parameters
2105: . constants - constant parameters
2106: - f0 - output values at the current point
2108: Level: intermediate
2110: .seealso: PetscDSSetBdResidual()
2111: @*/
2112: PetscErrorCode PetscDSGetBdResidual(PetscDS ds, PetscInt f,
2113: void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2114: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2115: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2116: PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
2117: void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2118: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2119: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2120: PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
2121: {
2122: PetscBdPointFunc *tmp0, *tmp1;
2123: PetscInt n0, n1;
2124: PetscErrorCode ierr;
2128: 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);
2129: PetscWeakFormGetBdResidual(ds->wf, NULL, 0, f, &n0, &tmp0, &n1, &tmp1);
2130: *f0 = tmp0 ? tmp0[0] : NULL;
2131: *f1 = tmp1 ? tmp1[0] : NULL;
2132: return(0);
2133: }
2135: /*@C
2136: PetscDSSetBdResidual - Get the pointwise boundary residual function for a given test field
2138: Not collective
2140: Input Parameters:
2141: + ds - The PetscDS
2142: . f - The test field number
2143: . f0 - boundary integrand for the test function term
2144: - f1 - boundary integrand for the test function gradient term
2146: Note: We are using a first order FEM model for the weak form:
2148: \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
2150: The calling sequence for the callbacks f0 and f1 is given by:
2152: $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2153: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2154: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2155: $ PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])
2157: + dim - the spatial dimension
2158: . Nf - the number of fields
2159: . uOff - the offset into u[] and u_t[] for each field
2160: . uOff_x - the offset into u_x[] for each field
2161: . u - each field evaluated at the current point
2162: . u_t - the time derivative of each field evaluated at the current point
2163: . u_x - the gradient of each field evaluated at the current point
2164: . aOff - the offset into a[] and a_t[] for each auxiliary field
2165: . aOff_x - the offset into a_x[] for each auxiliary field
2166: . a - each auxiliary field evaluated at the current point
2167: . a_t - the time derivative of each auxiliary field evaluated at the current point
2168: . a_x - the gradient of auxiliary each field evaluated at the current point
2169: . t - current time
2170: . x - coordinates of the current point
2171: . n - unit normal at the current point
2172: . numConstants - number of constant parameters
2173: . constants - constant parameters
2174: - f0 - output values at the current point
2176: Level: intermediate
2178: .seealso: PetscDSGetBdResidual()
2179: @*/
2180: PetscErrorCode PetscDSSetBdResidual(PetscDS ds, PetscInt f,
2181: void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2182: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2183: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2184: PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]),
2185: void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2186: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2187: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2188: PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
2189: {
2194: if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
2195: PetscWeakFormSetIndexBdResidual(ds->wf, NULL, 0, f, 0, f0, 0, f1);
2196: return(0);
2197: }
2199: /*@
2200: PetscDSHasBdJacobian - Signals that boundary Jacobian functions have been set
2202: Not collective
2204: Input Parameter:
2205: . ds - The PetscDS
2207: Output Parameter:
2208: . hasBdJac - flag that pointwise function for the boundary Jacobian has been set
2210: Level: intermediate
2212: .seealso: PetscDSHasJacobian(), PetscDSSetBdJacobian(), PetscDSGetBdJacobian()
2213: @*/
2214: PetscErrorCode PetscDSHasBdJacobian(PetscDS ds, PetscBool *hasBdJac)
2215: {
2221: PetscWeakFormHasBdJacobian(ds->wf, hasBdJac);
2222: return(0);
2223: }
2225: /*@C
2226: PetscDSGetBdJacobian - Get the pointwise boundary Jacobian function for given test and basis field
2228: Not collective
2230: Input Parameters:
2231: + ds - The PetscDS
2232: . f - The test field number
2233: - g - The field number
2235: Output Parameters:
2236: + g0 - integrand for the test and basis function term
2237: . g1 - integrand for the test function and basis function gradient term
2238: . g2 - integrand for the test function gradient and basis function term
2239: - g3 - integrand for the test function gradient and basis function gradient term
2241: Note: We are using a first order FEM model for the weak form:
2243: \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
2245: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
2247: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2248: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2249: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2250: $ PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[])
2252: + dim - the spatial dimension
2253: . Nf - the number of fields
2254: . uOff - the offset into u[] and u_t[] for each field
2255: . uOff_x - the offset into u_x[] for each field
2256: . u - each field evaluated at the current point
2257: . u_t - the time derivative of each field evaluated at the current point
2258: . u_x - the gradient of each field evaluated at the current point
2259: . aOff - the offset into a[] and a_t[] for each auxiliary field
2260: . aOff_x - the offset into a_x[] for each auxiliary field
2261: . a - each auxiliary field evaluated at the current point
2262: . a_t - the time derivative of each auxiliary field evaluated at the current point
2263: . a_x - the gradient of auxiliary each field evaluated at the current point
2264: . t - current time
2265: . u_tShift - the multiplier a for dF/dU_t
2266: . x - coordinates of the current point
2267: . n - normal at the current point
2268: . numConstants - number of constant parameters
2269: . constants - constant parameters
2270: - g0 - output values at the current point
2272: Level: intermediate
2274: .seealso: PetscDSSetBdJacobian()
2275: @*/
2276: PetscErrorCode PetscDSGetBdJacobian(PetscDS ds, PetscInt f, PetscInt g,
2277: void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2278: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2279: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2280: PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
2281: void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2282: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2283: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2284: PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
2285: void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2286: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2287: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2288: PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
2289: void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2290: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2291: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2292: PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2293: {
2294: PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3;
2295: PetscInt n0, n1, n2, n3;
2296: PetscErrorCode ierr;
2300: 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);
2301: 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);
2302: PetscWeakFormGetBdJacobian(ds->wf, NULL, 0, f, g, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);
2303: *g0 = tmp0 ? tmp0[0] : NULL;
2304: *g1 = tmp1 ? tmp1[0] : NULL;
2305: *g2 = tmp2 ? tmp2[0] : NULL;
2306: *g3 = tmp3 ? tmp3[0] : NULL;
2307: return(0);
2308: }
2310: /*@C
2311: PetscDSSetBdJacobian - Set the pointwise boundary Jacobian function for given test and basis field
2313: Not collective
2315: Input Parameters:
2316: + ds - The PetscDS
2317: . f - The test field number
2318: . g - The field number
2319: . g0 - integrand for the test and basis function term
2320: . g1 - integrand for the test function and basis function gradient term
2321: . g2 - integrand for the test function gradient and basis function term
2322: - g3 - integrand for the test function gradient and basis function gradient term
2324: Note: We are using a first order FEM model for the weak form:
2326: \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
2328: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
2330: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2331: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2332: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2333: $ PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[])
2335: + dim - the spatial dimension
2336: . Nf - the number of fields
2337: . uOff - the offset into u[] and u_t[] for each field
2338: . uOff_x - the offset into u_x[] for each field
2339: . u - each field evaluated at the current point
2340: . u_t - the time derivative of each field evaluated at the current point
2341: . u_x - the gradient of each field evaluated at the current point
2342: . aOff - the offset into a[] and a_t[] for each auxiliary field
2343: . aOff_x - the offset into a_x[] for each auxiliary field
2344: . a - each auxiliary field evaluated at the current point
2345: . a_t - the time derivative of each auxiliary field evaluated at the current point
2346: . a_x - the gradient of auxiliary each field evaluated at the current point
2347: . t - current time
2348: . u_tShift - the multiplier a for dF/dU_t
2349: . x - coordinates of the current point
2350: . n - normal at the current point
2351: . numConstants - number of constant parameters
2352: . constants - constant parameters
2353: - g0 - output values at the current point
2355: Level: intermediate
2357: .seealso: PetscDSGetBdJacobian()
2358: @*/
2359: PetscErrorCode PetscDSSetBdJacobian(PetscDS ds, PetscInt f, PetscInt g,
2360: void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2361: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2362: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2363: PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
2364: void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2365: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2366: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2367: PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
2368: void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2369: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2370: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2371: PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
2372: void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2373: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2374: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2375: PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2376: {
2385: if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
2386: if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
2387: PetscWeakFormSetIndexBdJacobian(ds->wf, NULL, 0, f, g, 0, g0, 0, g1, 0, g2, 0, g3);
2388: return(0);
2389: }
2391: /*@
2392: PetscDSHasBdJacobianPreconditioner - Signals that boundary Jacobian preconditioner functions have been set
2394: Not collective
2396: Input Parameter:
2397: . ds - The PetscDS
2399: Output Parameter:
2400: . hasBdJac - flag that pointwise function for the boundary Jacobian preconditioner has been set
2402: Level: intermediate
2404: .seealso: PetscDSHasJacobian(), PetscDSSetBdJacobian(), PetscDSGetBdJacobian()
2405: @*/
2406: PetscErrorCode PetscDSHasBdJacobianPreconditioner(PetscDS ds, PetscBool *hasBdJacPre)
2407: {
2413: PetscWeakFormHasBdJacobianPreconditioner(ds->wf, hasBdJacPre);
2414: return(0);
2415: }
2417: /*@C
2418: PetscDSGetBdJacobianPreconditioner - Get the pointwise boundary Jacobian preconditioner function for given test and basis field
2420: Not collective
2422: Input Parameters:
2423: + ds - The PetscDS
2424: . f - The test field number
2425: - g - The field number
2427: Output Parameters:
2428: + g0 - integrand for the test and basis function term
2429: . g1 - integrand for the test function and basis function gradient term
2430: . g2 - integrand for the test function gradient and basis function term
2431: - g3 - integrand for the test function gradient and basis function gradient term
2433: Note: We are using a first order FEM model for the weak form:
2435: \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
2437: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
2439: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2440: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2441: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2442: $ PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
2444: + dim - the spatial dimension
2445: . Nf - the number of fields
2446: . NfAux - the number of auxiliary fields
2447: . uOff - the offset into u[] and u_t[] for each field
2448: . uOff_x - the offset into u_x[] for each field
2449: . u - each field evaluated at the current point
2450: . u_t - the time derivative of each field evaluated at the current point
2451: . u_x - the gradient of each field evaluated at the current point
2452: . aOff - the offset into a[] and a_t[] for each auxiliary field
2453: . aOff_x - the offset into a_x[] for each auxiliary field
2454: . a - each auxiliary field evaluated at the current point
2455: . a_t - the time derivative of each auxiliary field evaluated at the current point
2456: . a_x - the gradient of auxiliary each field evaluated at the current point
2457: . t - current time
2458: . u_tShift - the multiplier a for dF/dU_t
2459: . x - coordinates of the current point
2460: . n - normal at the current point
2461: . numConstants - number of constant parameters
2462: . constants - constant parameters
2463: - g0 - output values at the current point
2465: This is not yet available in Fortran.
2467: Level: intermediate
2469: .seealso: PetscDSSetBdJacobianPreconditioner()
2470: @*/
2471: PetscErrorCode PetscDSGetBdJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g,
2472: void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2473: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2474: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2475: PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
2476: void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2477: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2478: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2479: PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
2480: void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2481: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2482: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2483: PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
2484: void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2485: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2486: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2487: PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2488: {
2489: PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3;
2490: PetscInt n0, n1, n2, n3;
2491: PetscErrorCode ierr;
2495: 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);
2496: 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);
2497: PetscWeakFormGetBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);
2498: *g0 = tmp0 ? tmp0[0] : NULL;
2499: *g1 = tmp1 ? tmp1[0] : NULL;
2500: *g2 = tmp2 ? tmp2[0] : NULL;
2501: *g3 = tmp3 ? tmp3[0] : NULL;
2502: return(0);
2503: }
2505: /*@C
2506: PetscDSSetBdJacobianPreconditioner - Set the pointwise boundary Jacobian preconditioner function for given test and basis field
2508: Not collective
2510: Input Parameters:
2511: + ds - The PetscDS
2512: . f - The test field number
2513: . g - The field number
2514: . g0 - integrand for the test and basis function term
2515: . g1 - integrand for the test function and basis function gradient term
2516: . g2 - integrand for the test function gradient and basis function term
2517: - g3 - integrand for the test function gradient and basis function gradient term
2519: Note: We are using a first order FEM model for the weak form:
2521: \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
2523: The calling sequence for the callbacks g0, g1, g2 and g3 is given by:
2525: $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2526: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2527: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2528: $ PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
2530: + dim - the spatial dimension
2531: . Nf - the number of fields
2532: . NfAux - the number of auxiliary fields
2533: . uOff - the offset into u[] and u_t[] for each field
2534: . uOff_x - the offset into u_x[] for each field
2535: . u - each field evaluated at the current point
2536: . u_t - the time derivative of each field evaluated at the current point
2537: . u_x - the gradient of each field evaluated at the current point
2538: . aOff - the offset into a[] and a_t[] for each auxiliary field
2539: . aOff_x - the offset into a_x[] for each auxiliary field
2540: . a - each auxiliary field evaluated at the current point
2541: . a_t - the time derivative of each auxiliary field evaluated at the current point
2542: . a_x - the gradient of auxiliary each field evaluated at the current point
2543: . t - current time
2544: . u_tShift - the multiplier a for dF/dU_t
2545: . x - coordinates of the current point
2546: . n - normal at the current point
2547: . numConstants - number of constant parameters
2548: . constants - constant parameters
2549: - g0 - output values at the current point
2551: This is not yet available in Fortran.
2553: Level: intermediate
2555: .seealso: PetscDSGetBdJacobianPreconditioner()
2556: @*/
2557: PetscErrorCode PetscDSSetBdJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g,
2558: void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2559: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2560: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2561: PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]),
2562: void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2563: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2564: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2565: PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]),
2566: void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2567: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2568: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2569: PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]),
2570: void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2571: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2572: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2573: PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2574: {
2583: if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
2584: if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g);
2585: PetscWeakFormSetIndexBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, g0, 0, g1, 0, g2, 0, g3);
2586: return(0);
2587: }
2589: /*@C
2590: PetscDSGetExactSolution - Get the pointwise exact solution function for a given test field
2592: Not collective
2594: Input Parameters:
2595: + prob - The PetscDS
2596: - f - The test field number
2598: Output Parameter:
2599: + exactSol - exact solution for the test field
2600: - exactCtx - exact solution context
2602: Note: The calling sequence for the solution functions is given by:
2604: $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2606: + dim - the spatial dimension
2607: . t - current time
2608: . x - coordinates of the current point
2609: . Nc - the number of field components
2610: . u - the solution field evaluated at the current point
2611: - ctx - a user context
2613: Level: intermediate
2615: .seealso: PetscDSSetExactSolution(), PetscDSGetExactSolutionTimeDerivative()
2616: @*/
2617: PetscErrorCode PetscDSGetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx)
2618: {
2621: 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);
2624: return(0);
2625: }
2627: /*@C
2628: PetscDSSetExactSolution - Set the pointwise exact solution function for a given test field
2630: Not collective
2632: Input Parameters:
2633: + prob - The PetscDS
2634: . f - The test field number
2635: . sol - solution function for the test fields
2636: - ctx - solution context or NULL
2638: Note: The calling sequence for solution functions is given by:
2640: $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2642: + dim - the spatial dimension
2643: . t - current time
2644: . x - coordinates of the current point
2645: . Nc - the number of field components
2646: . u - the solution field evaluated at the current point
2647: - ctx - a user context
2649: Level: intermediate
2651: .seealso: PetscDSGetExactSolution()
2652: @*/
2653: PetscErrorCode PetscDSSetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx)
2654: {
2659: if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
2660: PetscDSEnlarge_Static(prob, f+1);
2663: return(0);
2664: }
2666: /*@C
2667: PetscDSGetExactSolutionTimeDerivative - Get the pointwise time derivative of the exact solution function for a given test field
2669: Not collective
2671: Input Parameters:
2672: + prob - The PetscDS
2673: - f - The test field number
2675: Output Parameter:
2676: + exactSol - time derivative of the exact solution for the test field
2677: - exactCtx - time derivative of the exact solution context
2679: Note: The calling sequence for the solution functions is given by:
2681: $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2683: + dim - the spatial dimension
2684: . t - current time
2685: . x - coordinates of the current point
2686: . Nc - the number of field components
2687: . u - the solution field evaluated at the current point
2688: - ctx - a user context
2690: Level: intermediate
2692: .seealso: PetscDSSetExactSolutionTimeDerivative(), PetscDSGetExactSolution()
2693: @*/
2694: PetscErrorCode PetscDSGetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx)
2695: {
2698: 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);
2701: return(0);
2702: }
2704: /*@C
2705: PetscDSSetExactSolutionTimeDerivative - Set the pointwise time derivative of the exact solution function for a given test field
2707: Not collective
2709: Input Parameters:
2710: + prob - The PetscDS
2711: . f - The test field number
2712: . sol - time derivative of the solution function for the test fields
2713: - ctx - time derivative of the solution context or NULL
2715: Note: The calling sequence for solution functions is given by:
2717: $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2719: + dim - the spatial dimension
2720: . t - current time
2721: . x - coordinates of the current point
2722: . Nc - the number of field components
2723: . u - the solution field evaluated at the current point
2724: - ctx - a user context
2726: Level: intermediate
2728: .seealso: PetscDSGetExactSolutionTimeDerivative(), PetscDSSetExactSolution()
2729: @*/
2730: PetscErrorCode PetscDSSetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx)
2731: {
2736: if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f);
2737: PetscDSEnlarge_Static(prob, f+1);
2740: return(0);
2741: }
2743: /*@C
2744: PetscDSGetConstants - Returns the array of constants passed to point functions
2746: Not collective
2748: Input Parameter:
2749: . prob - The PetscDS object
2751: Output Parameters:
2752: + numConstants - The number of constants
2753: - constants - The array of constants, NULL if there are none
2755: Level: intermediate
2757: .seealso: PetscDSSetConstants(), PetscDSCreate()
2758: @*/
2759: PetscErrorCode PetscDSGetConstants(PetscDS prob, PetscInt *numConstants, const PetscScalar *constants[])
2760: {
2765: return(0);
2766: }
2768: /*@C
2769: PetscDSSetConstants - Set the array of constants passed to point functions
2771: Not collective
2773: Input Parameters:
2774: + prob - The PetscDS object
2775: . numConstants - The number of constants
2776: - constants - The array of constants, NULL if there are none
2778: Level: intermediate
2780: .seealso: PetscDSGetConstants(), PetscDSCreate()
2781: @*/
2782: PetscErrorCode PetscDSSetConstants(PetscDS prob, PetscInt numConstants, PetscScalar constants[])
2783: {
2788: if (numConstants != prob->numConstants) {
2789: PetscFree(prob->constants);
2790: prob->numConstants = numConstants;
2791: if (prob->numConstants) {
2792: PetscMalloc1(prob->numConstants, &prob->constants);
2793: } else {
2794: prob->constants = NULL;
2795: }
2796: }
2797: if (prob->numConstants) {
2799: PetscArraycpy(prob->constants, constants, prob->numConstants);
2800: }
2801: return(0);
2802: }
2804: /*@
2805: PetscDSGetFieldIndex - Returns the index of the given field
2807: Not collective
2809: Input Parameters:
2810: + prob - The PetscDS object
2811: - disc - The discretization object
2813: Output Parameter:
2814: . f - The field number
2816: Level: beginner
2818: .seealso: PetscGetDiscretization(), PetscDSGetNumFields(), PetscDSCreate()
2819: @*/
2820: PetscErrorCode PetscDSGetFieldIndex(PetscDS prob, PetscObject disc, PetscInt *f)
2821: {
2822: PetscInt g;
2827: *f = -1;
2828: for (g = 0; g < prob->Nf; ++g) {if (disc == prob->disc[g]) break;}
2829: if (g == prob->Nf) SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Field not found in PetscDS.");
2830: *f = g;
2831: return(0);
2832: }
2834: /*@
2835: PetscDSGetFieldSize - Returns the size of the given field in the full space basis
2837: Not collective
2839: Input Parameters:
2840: + prob - The PetscDS object
2841: - f - The field number
2843: Output Parameter:
2844: . size - The size
2846: Level: beginner
2848: .seealso: PetscDSGetFieldOffset(), PetscDSGetNumFields(), PetscDSCreate()
2849: @*/
2850: PetscErrorCode PetscDSGetFieldSize(PetscDS prob, PetscInt f, PetscInt *size)
2851: {
2857: 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);
2858: PetscDSSetUp(prob);
2859: *size = prob->Nb[f];
2860: return(0);
2861: }
2863: /*@
2864: PetscDSGetFieldOffset - Returns the offset of the given field in the full space basis
2866: Not collective
2868: Input Parameters:
2869: + prob - The PetscDS object
2870: - f - The field number
2872: Output Parameter:
2873: . off - The offset
2875: Level: beginner
2877: .seealso: PetscDSGetFieldSize(), PetscDSGetNumFields(), PetscDSCreate()
2878: @*/
2879: PetscErrorCode PetscDSGetFieldOffset(PetscDS prob, PetscInt f, PetscInt *off)
2880: {
2881: PetscInt size, g;
2887: 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);
2888: *off = 0;
2889: for (g = 0; g < f; ++g) {
2890: PetscDSGetFieldSize(prob, g, &size);
2891: *off += size;
2892: }
2893: return(0);
2894: }
2896: /*@
2897: PetscDSGetDimensions - Returns the size of the approximation space for each field on an evaluation point
2899: Not collective
2901: Input Parameter:
2902: . prob - The PetscDS object
2904: Output Parameter:
2905: . dimensions - The number of dimensions
2907: Level: beginner
2909: .seealso: PetscDSGetComponentOffsets(), PetscDSGetNumFields(), PetscDSCreate()
2910: @*/
2911: PetscErrorCode PetscDSGetDimensions(PetscDS prob, PetscInt *dimensions[])
2912: {
2917: PetscDSSetUp(prob);
2919: *dimensions = prob->Nb;
2920: return(0);
2921: }
2923: /*@
2924: PetscDSGetComponents - Returns the number of components for each field on an evaluation point
2926: Not collective
2928: Input Parameter:
2929: . prob - The PetscDS object
2931: Output Parameter:
2932: . components - The number of components
2934: Level: beginner
2936: .seealso: PetscDSGetComponentOffsets(), PetscDSGetNumFields(), PetscDSCreate()
2937: @*/
2938: PetscErrorCode PetscDSGetComponents(PetscDS prob, PetscInt *components[])
2939: {
2944: PetscDSSetUp(prob);
2946: *components = prob->Nc;
2947: return(0);
2948: }
2950: /*@
2951: PetscDSGetComponentOffset - Returns the offset of the given field on an evaluation point
2953: Not collective
2955: Input Parameters:
2956: + prob - The PetscDS object
2957: - f - The field number
2959: Output Parameter:
2960: . off - The offset
2962: Level: beginner
2964: .seealso: PetscDSGetNumFields(), PetscDSCreate()
2965: @*/
2966: PetscErrorCode PetscDSGetComponentOffset(PetscDS prob, PetscInt f, PetscInt *off)
2967: {
2971: 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);
2972: *off = prob->off[f];
2973: return(0);
2974: }
2976: /*@
2977: PetscDSGetComponentOffsets - Returns the offset of each field on an evaluation point
2979: Not collective
2981: Input Parameter:
2982: . prob - The PetscDS object
2984: Output Parameter:
2985: . offsets - The offsets
2987: Level: beginner
2989: .seealso: PetscDSGetNumFields(), PetscDSCreate()
2990: @*/
2991: PetscErrorCode PetscDSGetComponentOffsets(PetscDS prob, PetscInt *offsets[])
2992: {
2996: *offsets = prob->off;
2997: return(0);
2998: }
3000: /*@
3001: PetscDSGetComponentDerivativeOffsets - Returns the offset of each field derivative on an evaluation point
3003: Not collective
3005: Input Parameter:
3006: . prob - The PetscDS object
3008: Output Parameter:
3009: . offsets - The offsets
3011: Level: beginner
3013: .seealso: PetscDSGetNumFields(), PetscDSCreate()
3014: @*/
3015: PetscErrorCode PetscDSGetComponentDerivativeOffsets(PetscDS prob, PetscInt *offsets[])
3016: {
3020: *offsets = prob->offDer;
3021: return(0);
3022: }
3024: /*@C
3025: PetscDSGetTabulation - Return the basis tabulation at quadrature points for the volume discretization
3027: Not collective
3029: Input Parameter:
3030: . prob - The PetscDS object
3032: Output Parameter:
3033: . T - The basis function and derivatives tabulation at quadrature points for each field
3035: Level: intermediate
3037: .seealso: PetscDSCreate()
3038: @*/
3039: PetscErrorCode PetscDSGetTabulation(PetscDS prob, PetscTabulation *T[])
3040: {
3046: PetscDSSetUp(prob);
3047: *T = prob->T;
3048: return(0);
3049: }
3051: /*@C
3052: PetscDSGetFaceTabulation - Return the basis tabulation at quadrature points on the faces
3054: Not collective
3056: Input Parameter:
3057: . prob - The PetscDS object
3059: Output Parameter:
3060: . Tf - The basis function and derviative tabulation on each local face at quadrature points for each and field
3062: Level: intermediate
3064: .seealso: PetscDSGetTabulation(), PetscDSCreate()
3065: @*/
3066: PetscErrorCode PetscDSGetFaceTabulation(PetscDS prob, PetscTabulation *Tf[])
3067: {
3073: PetscDSSetUp(prob);
3074: *Tf = prob->Tf;
3075: return(0);
3076: }
3078: PetscErrorCode PetscDSGetEvaluationArrays(PetscDS prob, PetscScalar **u, PetscScalar **u_t, PetscScalar **u_x)
3079: {
3084: PetscDSSetUp(prob);
3088: return(0);
3089: }
3091: PetscErrorCode PetscDSGetWeakFormArrays(PetscDS prob, PetscScalar **f0, PetscScalar **f1, PetscScalar **g0, PetscScalar **g1, PetscScalar **g2, PetscScalar **g3)
3092: {
3097: PetscDSSetUp(prob);
3104: return(0);
3105: }
3107: PetscErrorCode PetscDSGetWorkspace(PetscDS prob, PetscReal **x, PetscScalar **basisReal, PetscScalar **basisDerReal, PetscScalar **testReal, PetscScalar **testDerReal)
3108: {
3113: PetscDSSetUp(prob);
3119: return(0);
3120: }
3122: /*@C
3123: 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().
3125: Collective on ds
3127: Input Parameters:
3128: + ds - The PetscDS object
3129: . type - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
3130: . name - The BC name
3131: . labelname - The label defining constrained points
3132: . field - The field to constrain
3133: . numcomps - The number of constrained field components (0 will constrain all fields)
3134: . comps - An array of constrained component numbers
3135: . bcFunc - A pointwise function giving boundary values
3136: . bcFunc_t - A pointwise function giving the time derviative of the boundary values, or NULL
3137: . numids - The number of DMLabel ids for constrained points
3138: . ids - An array of ids for constrained points
3139: - ctx - An optional user context for bcFunc
3141: Options Database Keys:
3142: + -bc_<boundary name> <num> - Overrides the boundary ids
3143: - -bc_<boundary name>_comp <num> - Overrides the boundary components
3145: Note:
3146: Both bcFunc abd bcFunc_t will depend on the boundary condition type. If the type if DM_BC_ESSENTIAL, Then the calling sequence is:
3148: $ bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])
3150: If the type is DM_BC_ESSENTIAL_FIELD or other _FIELD value, then the calling sequence is:
3152: $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
3153: $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
3154: $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
3155: $ PetscReal time, const PetscReal x[], PetscScalar bcval[])
3157: + dim - the spatial dimension
3158: . Nf - the number of fields
3159: . uOff - the offset into u[] and u_t[] for each field
3160: . uOff_x - the offset into u_x[] for each field
3161: . u - each field evaluated at the current point
3162: . u_t - the time derivative of each field evaluated at the current point
3163: . u_x - the gradient of each field evaluated at the current point
3164: . aOff - the offset into a[] and a_t[] for each auxiliary field
3165: . aOff_x - the offset into a_x[] for each auxiliary field
3166: . a - each auxiliary field evaluated at the current point
3167: . a_t - the time derivative of each auxiliary field evaluated at the current point
3168: . a_x - the gradient of auxiliary each field evaluated at the current point
3169: . t - current time
3170: . x - coordinates of the current point
3171: . numConstants - number of constant parameters
3172: . constants - constant parameters
3173: - bcval - output values at the current point
3175: Level: developer
3177: .seealso: PetscDSGetBoundary(), PetscDSSetResidual(), PetscDSSetBdResidual()
3178: @*/
3179: PetscErrorCode PetscDSAddBoundary(PetscDS ds, DMBoundaryConditionType type, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(void), void (*bcFunc_t)(void), PetscInt numids, const PetscInt *ids, void *ctx)
3180: {
3181: DSBoundary b;
3190: PetscNew(&b);
3191: PetscStrallocpy(name, (char **) &b->name);
3192: PetscStrallocpy(labelname, (char **) &b->labelname);
3193: PetscMalloc1(numcomps, &b->comps);
3194: if (numcomps) {PetscArraycpy(b->comps, comps, numcomps);}
3195: PetscMalloc1(numids, &b->ids);
3196: if (numids) {PetscArraycpy(b->ids, ids, numids);}
3197: b->type = type;
3198: b->field = field;
3199: b->numcomps = numcomps;
3200: b->func = bcFunc;
3201: b->func_t = bcFunc_t;
3202: b->numids = numids;
3203: b->ctx = ctx;
3204: b->next = ds->boundary;
3205: ds->boundary = b;
3206: return(0);
3207: }
3209: /*@C
3210: 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().
3212: Input Parameters:
3213: + ds - The PetscDS object
3214: . bd - The boundary condition number
3215: . type - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
3216: . name - The BC name
3217: . labelname - The label defining constrained points
3218: . field - The field to constrain
3219: . numcomps - The number of constrained field components
3220: . comps - An array of constrained component numbers
3221: . bcFunc - A pointwise function giving boundary values
3222: . bcFunc_t - A pointwise function giving the time derviative of the boundary values, or NULL
3223: . numids - The number of DMLabel ids for constrained points
3224: . ids - An array of ids for constrained points
3225: - ctx - An optional user context for bcFunc
3227: Note:
3228: 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.
3230: Level: developer
3232: .seealso: PetscDSAddBoundary(), PetscDSGetBoundary(), PetscDSGetNumBoundary()
3233: @*/
3234: PetscErrorCode PetscDSUpdateBoundary(PetscDS ds, PetscInt bd, DMBoundaryConditionType type, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(void), void (*bcFunc_t)(void), PetscInt numids, const PetscInt *ids, void *ctx)
3235: {
3236: DSBoundary b = ds->boundary;
3237: PetscInt n = 0;
3242: while (b) {
3243: if (n == bd) break;
3244: b = b->next;
3245: ++n;
3246: }
3247: if (!b) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n);
3248: if (name) {
3249: PetscFree(b->name);
3250: PetscStrallocpy(name, (char **) &b->name);
3251: }
3252: if (labelname) {
3253: PetscFree(b->labelname);
3254: PetscStrallocpy(labelname, (char **) &b->labelname);
3255: }
3256: if (numcomps >= 0 && numcomps != b->numcomps) {
3257: b->numcomps = numcomps;
3258: PetscFree(b->comps);
3259: PetscMalloc1(numcomps, &b->comps);
3260: if (numcomps) {PetscArraycpy(b->comps, comps, numcomps);}
3261: }
3262: if (numids >= 0 && numids != b->numids) {
3263: b->numids = numids;
3264: PetscFree(b->ids);
3265: PetscMalloc1(numids, &b->ids);
3266: if (numids) {PetscArraycpy(b->ids, ids, numids);}
3267: }
3268: b->type = type;
3269: if (field >= 0) {b->field = field;}
3270: if (bcFunc) {b->func = bcFunc;}
3271: if (bcFunc_t) {b->func_t = bcFunc_t;}
3272: if (ctx) {b->ctx = ctx;}
3273: return(0);
3274: }
3276: /*@
3277: PetscDSGetNumBoundary - Get the number of registered BC
3279: Input Parameters:
3280: . ds - The PetscDS object
3282: Output Parameters:
3283: . numBd - The number of BC
3285: Level: intermediate
3287: .seealso: PetscDSAddBoundary(), PetscDSGetBoundary()
3288: @*/
3289: PetscErrorCode PetscDSGetNumBoundary(PetscDS ds, PetscInt *numBd)
3290: {
3291: DSBoundary b = ds->boundary;
3296: *numBd = 0;
3297: while (b) {++(*numBd); b = b->next;}
3298: return(0);
3299: }
3301: /*@C
3302: PetscDSGetBoundary - Gets a boundary condition to the model
3304: Input Parameters:
3305: + ds - The PetscDS object
3306: - bd - The BC number
3308: Output Parameters:
3309: + type - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann)
3310: . name - The BC name
3311: . labelname - The label defining constrained points
3312: . field - The field to constrain
3313: . numcomps - The number of constrained field components
3314: . comps - An array of constrained component numbers
3315: . bcFunc - A pointwise function giving boundary values
3316: . bcFunc_t - A pointwise function giving the time derviative of the boundary values
3317: . numids - The number of DMLabel ids for constrained points
3318: . ids - An array of ids for constrained points
3319: - ctx - An optional user context for bcFunc
3321: Options Database Keys:
3322: + -bc_<boundary name> <num> - Overrides the boundary ids
3323: - -bc_<boundary name>_comp <num> - Overrides the boundary components
3325: Level: developer
3327: .seealso: PetscDSAddBoundary()
3328: @*/
3329: PetscErrorCode PetscDSGetBoundary(PetscDS ds, PetscInt bd, DMBoundaryConditionType *type, const char **name, const char **labelname, PetscInt *field, PetscInt *numcomps, const PetscInt **comps, void (**func)(void), void (**func_t)(void), PetscInt *numids, const PetscInt **ids, void **ctx)
3330: {
3331: DSBoundary b = ds->boundary;
3332: PetscInt n = 0;
3336: while (b) {
3337: if (n == bd) break;
3338: b = b->next;
3339: ++n;
3340: }
3341: if (!b) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n);
3342: if (type) {
3344: *type = b->type;
3345: }
3346: if (name) {
3348: *name = b->name;
3349: }
3350: if (labelname) {
3352: *labelname = b->labelname;
3353: }
3354: if (field) {
3356: *field = b->field;
3357: }
3358: if (numcomps) {
3360: *numcomps = b->numcomps;
3361: }
3362: if (comps) {
3364: *comps = b->comps;
3365: }
3366: if (func) {
3368: *func = b->func;
3369: }
3370: if (func_t) {
3372: *func_t = b->func_t;
3373: }
3374: if (numids) {
3376: *numids = b->numids;
3377: }
3378: if (ids) {
3380: *ids = b->ids;
3381: }
3382: if (ctx) {
3384: *ctx = b->ctx;
3385: }
3386: return(0);
3387: }
3389: /*@
3390: PetscDSCopyBoundary - Copy all boundary condition objects to the new problem
3392: Not collective
3394: Input Parameters:
3395: + ds - The source PetscDS object
3396: . numFields - The number of selected fields, or PETSC_DEFAULT for all fields
3397: - fields - The selected fields, or NULL for all fields
3399: Output Parameter:
3400: . newds - The target PetscDS, now with a copy of the boundary conditions
3402: Level: intermediate
3404: .seealso: PetscDSCopyEquations(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
3405: @*/
3406: PetscErrorCode PetscDSCopyBoundary(PetscDS ds, PetscInt numFields, const PetscInt fields[], PetscDS newds)
3407: {
3408: DSBoundary b, next, *lastnext;
3414: if (ds == newds) return(0);
3415: next = newds->boundary;
3416: while (next) {
3417: DSBoundary b = next;
3419: next = b->next;
3420: PetscFree(b->comps);
3421: PetscFree(b->ids);
3422: PetscFree(b->name);
3423: PetscFree(b->labelname);
3424: PetscFree(b);
3425: }
3426: lastnext = &(newds->boundary);
3427: for (b = ds->boundary; b; b = b->next) {
3428: DSBoundary bNew;
3429: PetscInt fieldNew = -1;
3431: if (numFields > 0 && fields) {
3432: PetscInt f;
3434: for (f = 0; f < numFields; ++f) if (b->field == fields[f]) break;
3435: if (f == numFields) continue;
3436: fieldNew = f;
3437: }
3438: PetscNew(&bNew);
3439: bNew->numcomps = b->numcomps;
3440: PetscMalloc1(bNew->numcomps, &bNew->comps);
3441: PetscArraycpy(bNew->comps, b->comps, bNew->numcomps);
3442: bNew->numids = b->numids;
3443: PetscMalloc1(bNew->numids, &bNew->ids);
3444: PetscArraycpy(bNew->ids, b->ids, bNew->numids);
3445: PetscStrallocpy(b->labelname,(char **) &(bNew->labelname));
3446: PetscStrallocpy(b->name,(char **) &(bNew->name));
3447: bNew->ctx = b->ctx;
3448: bNew->type = b->type;
3449: bNew->field = fieldNew < 0 ? b->field : fieldNew;
3450: bNew->func = b->func;
3452: *lastnext = bNew;
3453: lastnext = &(bNew->next);
3454: }
3455: return(0);
3456: }
3458: /*@
3459: PetscDSSelectDiscretizations - Copy discretizations to the new problem with different field layout
3461: Not collective
3463: Input Parameter:
3464: + prob - The PetscDS object
3465: . numFields - Number of new fields
3466: - fields - Old field number for each new field
3468: Output Parameter:
3469: . newprob - The PetscDS copy
3471: Level: intermediate
3473: .seealso: PetscDSSelectEquations(), PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
3474: @*/
3475: PetscErrorCode PetscDSSelectDiscretizations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob)
3476: {
3477: PetscInt Nf, Nfn, fn;
3484: PetscDSGetNumFields(prob, &Nf);
3485: PetscDSGetNumFields(newprob, &Nfn);
3486: 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);
3487: for (fn = 0; fn < numFields; ++fn) {
3488: const PetscInt f = fields ? fields[fn] : fn;
3489: PetscObject disc;
3491: if (f >= Nf) continue;
3492: PetscDSGetDiscretization(prob, f, &disc);
3493: PetscDSSetDiscretization(newprob, fn, disc);
3494: }
3495: return(0);
3496: }
3498: /*@
3499: PetscDSSelectEquations - Copy pointwise function pointers to the new problem with different field layout
3501: Not collective
3503: Input Parameter:
3504: + prob - The PetscDS object
3505: . numFields - Number of new fields
3506: - fields - Old field number for each new field
3508: Output Parameter:
3509: . newprob - The PetscDS copy
3511: Level: intermediate
3513: .seealso: PetscDSSelectDiscretizations(), PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
3514: @*/
3515: PetscErrorCode PetscDSSelectEquations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob)
3516: {
3517: PetscInt Nf, Nfn, fn, gn;
3524: PetscDSGetNumFields(prob, &Nf);
3525: PetscDSGetNumFields(newprob, &Nfn);
3526: 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);
3527: for (fn = 0; fn < numFields; ++fn) {
3528: const PetscInt f = fields ? fields[fn] : fn;
3529: PetscPointFunc obj;
3530: PetscPointFunc f0, f1;
3531: PetscBdPointFunc f0Bd, f1Bd;
3532: PetscRiemannFunc r;
3534: if (f >= Nf) continue;
3535: PetscDSGetObjective(prob, f, &obj);
3536: PetscDSGetResidual(prob, f, &f0, &f1);
3537: PetscDSGetBdResidual(prob, f, &f0Bd, &f1Bd);
3538: PetscDSGetRiemannSolver(prob, f, &r);
3539: PetscDSSetObjective(newprob, fn, obj);
3540: PetscDSSetResidual(newprob, fn, f0, f1);
3541: PetscDSSetBdResidual(newprob, fn, f0Bd, f1Bd);
3542: PetscDSSetRiemannSolver(newprob, fn, r);
3543: for (gn = 0; gn < numFields; ++gn) {
3544: const PetscInt g = fields ? fields[gn] : gn;
3545: PetscPointJac g0, g1, g2, g3;
3546: PetscPointJac g0p, g1p, g2p, g3p;
3547: PetscBdPointJac g0Bd, g1Bd, g2Bd, g3Bd;
3549: if (g >= Nf) continue;
3550: PetscDSGetJacobian(prob, f, g, &g0, &g1, &g2, &g3);
3551: PetscDSGetJacobianPreconditioner(prob, f, g, &g0p, &g1p, &g2p, &g3p);
3552: PetscDSGetBdJacobian(prob, f, g, &g0Bd, &g1Bd, &g2Bd, &g3Bd);
3553: PetscDSSetJacobian(newprob, fn, gn, g0, g1, g2, g3);
3554: PetscDSSetJacobianPreconditioner(newprob, fn, gn, g0p, g1p, g2p, g3p);
3555: PetscDSSetBdJacobian(newprob, fn, gn, g0Bd, g1Bd, g2Bd, g3Bd);
3556: }
3557: }
3558: return(0);
3559: }
3561: /*@
3562: PetscDSCopyEquations - Copy all pointwise function pointers to the new problem
3564: Not collective
3566: Input Parameter:
3567: . prob - The PetscDS object
3569: Output Parameter:
3570: . newprob - The PetscDS copy
3572: Level: intermediate
3574: .seealso: PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
3575: @*/
3576: PetscErrorCode PetscDSCopyEquations(PetscDS prob, PetscDS newprob)
3577: {
3578: PetscInt Nf, Ng;
3584: PetscDSGetNumFields(prob, &Nf);
3585: PetscDSGetNumFields(newprob, &Ng);
3586: if (Nf != Ng) SETERRQ2(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_SIZ, "Number of fields must match %D != %D", Nf, Ng);
3587: PetscDSSelectEquations(prob, Nf, NULL, newprob);
3588: return(0);
3589: }
3590: /*@
3591: PetscDSCopyConstants - Copy all constants to the new problem
3593: Not collective
3595: Input Parameter:
3596: . prob - The PetscDS object
3598: Output Parameter:
3599: . newprob - The PetscDS copy
3601: Level: intermediate
3603: .seealso: PetscDSCopyBoundary(), PetscDSCopyEquations(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate()
3604: @*/
3605: PetscErrorCode PetscDSCopyConstants(PetscDS prob, PetscDS newprob)
3606: {
3607: PetscInt Nc;
3608: const PetscScalar *constants;
3609: PetscErrorCode ierr;
3614: PetscDSGetConstants(prob, &Nc, &constants);
3615: PetscDSSetConstants(newprob, Nc, (PetscScalar *) constants);
3616: return(0);
3617: }
3619: PetscErrorCode PetscDSGetHeightSubspace(PetscDS prob, PetscInt height, PetscDS *subprob)
3620: {
3621: PetscInt dim, Nf, f;
3627: if (height == 0) {*subprob = prob; return(0);}
3628: PetscDSGetNumFields(prob, &Nf);
3629: PetscDSGetSpatialDimension(prob, &dim);
3630: if (height > dim) SETERRQ2(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_OUTOFRANGE, "DS can only handle height in [0, %D], not %D", dim, height);
3631: if (!prob->subprobs) {PetscCalloc1(dim, &prob->subprobs);}
3632: if (!prob->subprobs[height-1]) {
3633: PetscInt cdim;
3635: PetscDSCreate(PetscObjectComm((PetscObject) prob), &prob->subprobs[height-1]);
3636: PetscDSGetCoordinateDimension(prob, &cdim);
3637: PetscDSSetCoordinateDimension(prob->subprobs[height-1], cdim);
3638: for (f = 0; f < Nf; ++f) {
3639: PetscFE subfe;
3640: PetscObject obj;
3641: PetscClassId id;
3643: PetscDSGetDiscretization(prob, f, &obj);
3644: PetscObjectGetClassId(obj, &id);
3645: if (id == PETSCFE_CLASSID) {PetscFEGetHeightSubspace((PetscFE) obj, height, &subfe);}
3646: else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unsupported discretization type for field %d", f);
3647: PetscDSSetDiscretization(prob->subprobs[height-1], f, (PetscObject) subfe);
3648: }
3649: }
3650: *subprob = prob->subprobs[height-1];
3651: return(0);
3652: }
3654: PetscErrorCode PetscDSGetDiscType_Internal(PetscDS ds, PetscInt f, PetscDiscType *disctype)
3655: {
3656: PetscObject obj;
3657: PetscClassId id;
3658: PetscInt Nf;
3664: *disctype = PETSC_DISC_NONE;
3665: PetscDSGetNumFields(ds, &Nf);
3666: if (f >= Nf) SETERRQ2(PetscObjectComm((PetscObject) ds), PETSC_ERR_ARG_SIZ, "Field %D must be in [0, %D)", f, Nf);
3667: PetscDSGetDiscretization(ds, f, &obj);
3668: if (obj) {
3669: PetscObjectGetClassId(obj, &id);
3670: if (id == PETSCFE_CLASSID) *disctype = PETSC_DISC_FE;
3671: else *disctype = PETSC_DISC_FV;
3672: }
3673: return(0);
3674: }
3676: static PetscErrorCode PetscDSDestroy_Basic(PetscDS ds)
3677: {
3681: PetscFree(ds->data);
3682: return(0);
3683: }
3685: static PetscErrorCode PetscDSInitialize_Basic(PetscDS ds)
3686: {
3688: ds->ops->setfromoptions = NULL;
3689: ds->ops->setup = NULL;
3690: ds->ops->view = NULL;
3691: ds->ops->destroy = PetscDSDestroy_Basic;
3692: return(0);
3693: }
3695: /*MC
3696: PETSCDSBASIC = "basic" - A discrete system with pointwise residual and boundary residual functions
3698: Level: intermediate
3700: .seealso: PetscDSType, PetscDSCreate(), PetscDSSetType()
3701: M*/
3703: PETSC_EXTERN PetscErrorCode PetscDSCreate_Basic(PetscDS ds)
3704: {
3705: PetscDS_Basic *b;
3710: PetscNewLog(ds, &b);
3711: ds->data = b;
3713: PetscDSInitialize_Basic(ds);
3714: return(0);
3715: }