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: Sample usage:
31: .vb
32: PetscDSRegister("my_ds", MyPetscDSCreate);
33: .ve
35: Then, your PetscDS type can be chosen with the procedural interface via
36: .vb
37: PetscDSCreate(MPI_Comm, PetscDS *);
38: PetscDSSetType(PetscDS, "my_ds");
39: .ve
40: or at runtime via the option
41: .vb
42: -petscds_type my_ds
43: .ve
45: Level: advanced
47: Note:
48: `PetscDSRegister()` may be called multiple times to add several user-defined `PetscDSs`
50: Fortran Note:
51: Not available from Fortran
53: .seealso: `PetscDSType`, `PetscDS`, `PetscDSRegisterAll()`, `PetscDSRegisterDestroy()`
54: @*/
55: PetscErrorCode PetscDSRegister(const char sname[], PetscErrorCode (*function)(PetscDS))
56: {
57: PetscFunctionBegin;
58: PetscCall(PetscFunctionListAdd(&PetscDSList, sname, function));
59: PetscFunctionReturn(PETSC_SUCCESS);
60: }
62: /*@C
63: PetscDSSetType - Builds a particular `PetscDS`
65: Collective on prob
67: Input Parameters:
68: + prob - The `PetscDS` object
69: - name - The `PetscDSType`
71: Options Database Key:
72: . -petscds_type <type> - Sets the PetscDS type; use -help for a list of available types
74: Level: intermediate
76: Fortran Note:
77: Not available from Fortran
79: .seealso: `PetscDSType`, `PetscDS`, `PetscDSGetType()`, `PetscDSCreate()`
80: @*/
81: PetscErrorCode PetscDSSetType(PetscDS prob, PetscDSType name)
82: {
83: PetscErrorCode (*r)(PetscDS);
84: PetscBool match;
86: PetscFunctionBegin;
88: PetscCall(PetscObjectTypeCompare((PetscObject)prob, name, &match));
89: if (match) PetscFunctionReturn(PETSC_SUCCESS);
91: PetscCall(PetscDSRegisterAll());
92: PetscCall(PetscFunctionListFind(PetscDSList, name, &r));
93: PetscCheck(r, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDS type: %s", name);
95: PetscTryTypeMethod(prob, destroy);
96: prob->ops->destroy = NULL;
98: PetscCall((*r)(prob));
99: PetscCall(PetscObjectChangeTypeName((PetscObject)prob, name));
100: PetscFunctionReturn(PETSC_SUCCESS);
101: }
103: /*@C
104: PetscDSGetType - Gets the `PetscDSType` name (as a string) from the `PetscDS`
106: Not Collective
108: Input Parameter:
109: . prob - The `PetscDS`
111: Output Parameter:
112: . name - The `PetscDSType` name
114: Level: intermediate
116: Fortran Note:
117: Not available from Fortran
119: .seealso: `PetscDSType`, `PetscDS`, `PetscDSSetType()`, `PetscDSCreate()`
120: @*/
121: PetscErrorCode PetscDSGetType(PetscDS prob, PetscDSType *name)
122: {
123: PetscFunctionBegin;
126: PetscCall(PetscDSRegisterAll());
127: *name = ((PetscObject)prob)->type_name;
128: PetscFunctionReturn(PETSC_SUCCESS);
129: }
131: static PetscErrorCode PetscDSView_Ascii(PetscDS ds, PetscViewer viewer)
132: {
133: PetscViewerFormat format;
134: const PetscScalar *constants;
135: PetscInt Nf, numConstants, f;
137: PetscFunctionBegin;
138: PetscCall(PetscDSGetNumFields(ds, &Nf));
139: PetscCall(PetscViewerGetFormat(viewer, &format));
140: PetscCall(PetscViewerASCIIPrintf(viewer, "Discrete System with %" PetscInt_FMT " fields\n", Nf));
141: PetscCall(PetscViewerASCIIPushTab(viewer));
142: PetscCall(PetscViewerASCIIPrintf(viewer, " cell total dim %" PetscInt_FMT " total comp %" PetscInt_FMT "\n", ds->totDim, ds->totComp));
143: if (ds->isCohesive) PetscCall(PetscViewerASCIIPrintf(viewer, " cohesive cell\n"));
144: for (f = 0; f < Nf; ++f) {
145: DSBoundary b;
146: PetscObject obj;
147: PetscClassId id;
148: PetscQuadrature q;
149: const char *name;
150: PetscInt Nc, Nq, Nqc;
152: PetscCall(PetscDSGetDiscretization(ds, f, &obj));
153: PetscCall(PetscObjectGetClassId(obj, &id));
154: PetscCall(PetscObjectGetName(obj, &name));
155: PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s", name ? name : "<unknown>"));
156: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
157: if (id == PETSCFE_CLASSID) {
158: PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
159: PetscCall(PetscFEGetQuadrature((PetscFE)obj, &q));
160: PetscCall(PetscViewerASCIIPrintf(viewer, " FEM"));
161: } else if (id == PETSCFV_CLASSID) {
162: PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc));
163: PetscCall(PetscFVGetQuadrature((PetscFV)obj, &q));
164: PetscCall(PetscViewerASCIIPrintf(viewer, " FVM"));
165: } else SETERRQ(PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, f);
166: if (Nc > 1) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " components", Nc));
167: else PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " component ", Nc));
168: if (ds->implicit[f]) PetscCall(PetscViewerASCIIPrintf(viewer, " (implicit)"));
169: else PetscCall(PetscViewerASCIIPrintf(viewer, " (explicit)"));
170: if (q) {
171: PetscCall(PetscQuadratureGetData(q, NULL, &Nqc, &Nq, NULL, NULL));
172: PetscCall(PetscViewerASCIIPrintf(viewer, " (Nq %" PetscInt_FMT " Nqc %" PetscInt_FMT ")", Nq, Nqc));
173: }
174: PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "-jet", ds->jetDegree[f]));
175: PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
176: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
177: PetscCall(PetscViewerASCIIPushTab(viewer));
178: if (id == PETSCFE_CLASSID) PetscCall(PetscFEView((PetscFE)obj, viewer));
179: else if (id == PETSCFV_CLASSID) PetscCall(PetscFVView((PetscFV)obj, viewer));
180: PetscCall(PetscViewerASCIIPopTab(viewer));
182: for (b = ds->boundary; b; b = b->next) {
183: char *name;
184: PetscInt c, i;
186: if (b->field != f) continue;
187: PetscCall(PetscViewerASCIIPushTab(viewer));
188: PetscCall(PetscViewerASCIIPrintf(viewer, "Boundary %s (%s) %s\n", b->name, b->lname, DMBoundaryConditionTypes[b->type]));
189: if (!b->Nc) {
190: PetscCall(PetscViewerASCIIPrintf(viewer, " all components\n"));
191: } else {
192: PetscCall(PetscViewerASCIIPrintf(viewer, " components: "));
193: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
194: for (c = 0; c < b->Nc; ++c) {
195: if (c > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
196: PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT, b->comps[c]));
197: }
198: PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
199: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
200: }
201: PetscCall(PetscViewerASCIIPrintf(viewer, " values: "));
202: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
203: for (i = 0; i < b->Nv; ++i) {
204: if (i > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
205: PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT, b->values[i]));
206: }
207: PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
208: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
209: #if defined(__clang__)
210: #pragma clang diagnostic push
211: #pragma clang diagnostic ignored "-Wformat-pedantic"
212: #elif defined(__GNUC__) || defined(__GNUG__)
213: #pragma GCC diagnostic push
214: #pragma GCC diagnostic ignored "-Wformat"
215: #endif
216: if (b->func) {
217: PetscCall(PetscDLAddr(b->func, &name));
218: if (name) PetscCall(PetscViewerASCIIPrintf(viewer, " func: %s\n", name));
219: else PetscCall(PetscViewerASCIIPrintf(viewer, " func: %p\n", b->func));
220: PetscCall(PetscFree(name));
221: }
222: if (b->func_t) {
223: PetscCall(PetscDLAddr(b->func_t, &name));
224: if (name) PetscCall(PetscViewerASCIIPrintf(viewer, " func_t: %s\n", name));
225: else PetscCall(PetscViewerASCIIPrintf(viewer, " func_t: %p\n", b->func_t));
226: PetscCall(PetscFree(name));
227: }
228: #if defined(__clang__)
229: #pragma clang diagnostic pop
230: #elif defined(__GNUC__) || defined(__GNUG__)
231: #pragma GCC diagnostic pop
232: #endif
233: PetscCall(PetscWeakFormView(b->wf, viewer));
234: PetscCall(PetscViewerASCIIPopTab(viewer));
235: }
236: }
237: PetscCall(PetscDSGetConstants(ds, &numConstants, &constants));
238: if (numConstants) {
239: PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " constants\n", numConstants));
240: PetscCall(PetscViewerASCIIPushTab(viewer));
241: for (f = 0; f < numConstants; ++f) PetscCall(PetscViewerASCIIPrintf(viewer, "%g\n", (double)PetscRealPart(constants[f])));
242: PetscCall(PetscViewerASCIIPopTab(viewer));
243: }
244: PetscCall(PetscWeakFormView(ds->wf, viewer));
245: PetscCall(PetscViewerASCIIPopTab(viewer));
246: PetscFunctionReturn(PETSC_SUCCESS);
247: }
249: /*@C
250: PetscDSViewFromOptions - View a `PetscDS` based on values in the options database
252: Collective on PetscDS
254: Input Parameters:
255: + A - the `PetscDS` object
256: . obj - Optional object
257: - name - command line option
259: Level: intermediate
261: .seealso: `PetscDSType`, `PetscDS`, `PetscDSView()`, `PetscObjectViewFromOptions()`, `PetscDSCreate()`
262: @*/
263: PetscErrorCode PetscDSViewFromOptions(PetscDS A, PetscObject obj, const char name[])
264: {
265: PetscFunctionBegin;
267: PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
268: PetscFunctionReturn(PETSC_SUCCESS);
269: }
271: /*@C
272: PetscDSView - Views a `PetscDS`
274: Collective on prob
276: Input Parameters:
277: + prob - the `PetscDS` object to view
278: - v - the viewer
280: Level: developer
282: .seealso: `PetscDSType`, `PetscDS`, `PetscViewer`, `PetscDSDestroy()`
283: @*/
284: PetscErrorCode PetscDSView(PetscDS prob, PetscViewer v)
285: {
286: PetscBool iascii;
288: PetscFunctionBegin;
290: if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)prob), &v));
292: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii));
293: if (iascii) PetscCall(PetscDSView_Ascii(prob, v));
294: PetscTryTypeMethod(prob, view, v);
295: PetscFunctionReturn(PETSC_SUCCESS);
296: }
298: /*@
299: PetscDSSetFromOptions - sets parameters in a `PetscDS` from the options database
301: Collective on prob
303: Input Parameter:
304: . prob - the `PetscDS` object to set options for
306: Options Database Keys:
307: + -petscds_type <type> - Set the `PetscDS` type
308: . -petscds_view <view opt> - View the `PetscDS`
309: . -petscds_jac_pre - Turn formation of a separate Jacobian preconditioner on or off
310: . -bc_<name> <ids> - Specify a list of label ids for a boundary condition
311: - -bc_<name>_comp <comps> - Specify a list of field components to constrain for a boundary condition
313: Level: intermediate
315: .seealso: `PetscDS`, `PetscDSView()`
316: @*/
317: PetscErrorCode PetscDSSetFromOptions(PetscDS prob)
318: {
319: DSBoundary b;
320: const char *defaultType;
321: char name[256];
322: PetscBool flg;
324: PetscFunctionBegin;
326: if (!((PetscObject)prob)->type_name) {
327: defaultType = PETSCDSBASIC;
328: } else {
329: defaultType = ((PetscObject)prob)->type_name;
330: }
331: PetscCall(PetscDSRegisterAll());
333: PetscObjectOptionsBegin((PetscObject)prob);
334: for (b = prob->boundary; b; b = b->next) {
335: char optname[1024];
336: PetscInt ids[1024], len = 1024;
337: PetscBool flg;
339: PetscCall(PetscSNPrintf(optname, sizeof(optname), "-bc_%s", b->name));
340: PetscCall(PetscMemzero(ids, sizeof(ids)));
341: PetscCall(PetscOptionsIntArray(optname, "List of boundary IDs", "", ids, &len, &flg));
342: if (flg) {
343: b->Nv = len;
344: PetscCall(PetscFree(b->values));
345: PetscCall(PetscMalloc1(len, &b->values));
346: PetscCall(PetscArraycpy(b->values, ids, len));
347: PetscCall(PetscWeakFormRewriteKeys(b->wf, b->label, len, b->values));
348: }
349: len = 1024;
350: PetscCall(PetscSNPrintf(optname, sizeof(optname), "-bc_%s_comp", b->name));
351: PetscCall(PetscMemzero(ids, sizeof(ids)));
352: PetscCall(PetscOptionsIntArray(optname, "List of boundary field components", "", ids, &len, &flg));
353: if (flg) {
354: b->Nc = len;
355: PetscCall(PetscFree(b->comps));
356: PetscCall(PetscMalloc1(len, &b->comps));
357: PetscCall(PetscArraycpy(b->comps, ids, len));
358: }
359: }
360: PetscCall(PetscOptionsFList("-petscds_type", "Discrete System", "PetscDSSetType", PetscDSList, defaultType, name, 256, &flg));
361: if (flg) {
362: PetscCall(PetscDSSetType(prob, name));
363: } else if (!((PetscObject)prob)->type_name) {
364: PetscCall(PetscDSSetType(prob, defaultType));
365: }
366: PetscCall(PetscOptionsBool("-petscds_jac_pre", "Discrete System", "PetscDSUseJacobianPreconditioner", prob->useJacPre, &prob->useJacPre, &flg));
367: PetscTryTypeMethod(prob, setfromoptions);
368: /* process any options handlers added with PetscObjectAddOptionsHandler() */
369: PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)prob, PetscOptionsObject));
370: PetscOptionsEnd();
371: if (prob->Nf) PetscCall(PetscDSViewFromOptions(prob, NULL, "-petscds_view"));
372: PetscFunctionReturn(PETSC_SUCCESS);
373: }
375: /*@C
376: PetscDSSetUp - Construct data structures for the `PetscDS`
378: Collective on prob
380: Input Parameter:
381: . prob - the `PetscDS` object to setup
383: Level: developer
385: .seealso: `PetscDS`, `PetscDSView()`, `PetscDSDestroy()`
386: @*/
387: PetscErrorCode PetscDSSetUp(PetscDS prob)
388: {
389: const PetscInt Nf = prob->Nf;
390: PetscBool hasH = PETSC_FALSE;
391: PetscInt dim, dimEmbed, NbMax = 0, NcMax = 0, NqMax = 0, NsMax = 1, f;
393: PetscFunctionBegin;
395: if (prob->setup) PetscFunctionReturn(PETSC_SUCCESS);
396: /* Calculate sizes */
397: PetscCall(PetscDSGetSpatialDimension(prob, &dim));
398: PetscCall(PetscDSGetCoordinateDimension(prob, &dimEmbed));
399: prob->totDim = prob->totComp = 0;
400: PetscCall(PetscMalloc2(Nf, &prob->Nc, Nf, &prob->Nb));
401: PetscCall(PetscCalloc2(Nf + 1, &prob->off, Nf + 1, &prob->offDer));
402: PetscCall(PetscCalloc6(Nf + 1, &prob->offCohesive[0], Nf + 1, &prob->offCohesive[1], Nf + 1, &prob->offCohesive[2], Nf + 1, &prob->offDerCohesive[0], Nf + 1, &prob->offDerCohesive[1], Nf + 1, &prob->offDerCohesive[2]));
403: PetscCall(PetscMalloc2(Nf, &prob->T, Nf, &prob->Tf));
404: for (f = 0; f < Nf; ++f) {
405: PetscObject obj;
406: PetscClassId id;
407: PetscQuadrature q = NULL;
408: PetscInt Nq = 0, Nb, Nc;
410: PetscCall(PetscDSGetDiscretization(prob, f, &obj));
411: if (prob->jetDegree[f] > 1) hasH = PETSC_TRUE;
412: if (!obj) {
413: /* Empty mesh */
414: Nb = Nc = 0;
415: prob->T[f] = prob->Tf[f] = NULL;
416: } else {
417: PetscCall(PetscObjectGetClassId(obj, &id));
418: if (id == PETSCFE_CLASSID) {
419: PetscFE fe = (PetscFE)obj;
421: PetscCall(PetscFEGetQuadrature(fe, &q));
422: PetscCall(PetscFEGetDimension(fe, &Nb));
423: PetscCall(PetscFEGetNumComponents(fe, &Nc));
424: PetscCall(PetscFEGetCellTabulation(fe, prob->jetDegree[f], &prob->T[f]));
425: PetscCall(PetscFEGetFaceTabulation(fe, prob->jetDegree[f], &prob->Tf[f]));
426: } else if (id == PETSCFV_CLASSID) {
427: PetscFV fv = (PetscFV)obj;
429: PetscCall(PetscFVGetQuadrature(fv, &q));
430: PetscCall(PetscFVGetNumComponents(fv, &Nc));
431: Nb = Nc;
432: PetscCall(PetscFVGetCellTabulation(fv, &prob->T[f]));
433: /* TODO: should PetscFV also have face tabulation? Otherwise there will be a null pointer in prob->basisFace */
434: } else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, f);
435: }
436: prob->Nc[f] = Nc;
437: prob->Nb[f] = Nb;
438: prob->off[f + 1] = Nc + prob->off[f];
439: prob->offDer[f + 1] = Nc * dim + prob->offDer[f];
440: prob->offCohesive[0][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) + prob->offCohesive[0][f];
441: prob->offDerCohesive[0][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) * dimEmbed + prob->offDerCohesive[0][f];
442: prob->offCohesive[1][f] = (prob->cohesive[f] ? 0 : Nc) + prob->offCohesive[0][f];
443: prob->offDerCohesive[1][f] = (prob->cohesive[f] ? 0 : Nc) * dimEmbed + prob->offDerCohesive[0][f];
444: prob->offCohesive[2][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) + prob->offCohesive[2][f];
445: prob->offDerCohesive[2][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) * dimEmbed + prob->offDerCohesive[2][f];
446: if (q) PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Nq, NULL, NULL));
447: NqMax = PetscMax(NqMax, Nq);
448: NbMax = PetscMax(NbMax, Nb);
449: NcMax = PetscMax(NcMax, Nc);
450: prob->totDim += Nb;
451: prob->totComp += Nc;
452: /* There are two faces for all fields on a cohesive cell, except for cohesive fields */
453: if (prob->isCohesive && !prob->cohesive[f]) prob->totDim += Nb;
454: }
455: prob->offCohesive[1][Nf] = prob->offCohesive[0][Nf];
456: prob->offDerCohesive[1][Nf] = prob->offDerCohesive[0][Nf];
457: /* Allocate works space */
458: NsMax = 2; /* A non-cohesive discretizations can be used on a cohesive cell, so we need this extra workspace for all DS */
459: PetscCall(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));
460: PetscCall(PetscMalloc5(dimEmbed, &prob->x, NbMax * NcMax, &prob->basisReal, NbMax * NcMax * dimEmbed, &prob->basisDerReal, NbMax * NcMax, &prob->testReal, NbMax * NcMax * dimEmbed, &prob->testDerReal));
461: PetscCall(PetscMalloc6(NsMax * NqMax * NcMax, &prob->f0, NsMax * NqMax * NcMax * dimEmbed, &prob->f1, NsMax * NsMax * NqMax * NcMax * NcMax, &prob->g0, NsMax * NsMax * NqMax * NcMax * NcMax * dimEmbed, &prob->g1, NsMax * NsMax * NqMax * NcMax * NcMax * dimEmbed,
462: &prob->g2, NsMax * NsMax * NqMax * NcMax * NcMax * dimEmbed * dimEmbed, &prob->g3));
463: PetscTryTypeMethod(prob, setup);
464: prob->setup = PETSC_TRUE;
465: PetscFunctionReturn(PETSC_SUCCESS);
466: }
468: static PetscErrorCode PetscDSDestroyStructs_Static(PetscDS prob)
469: {
470: PetscFunctionBegin;
471: PetscCall(PetscFree2(prob->Nc, prob->Nb));
472: PetscCall(PetscFree2(prob->off, prob->offDer));
473: PetscCall(PetscFree6(prob->offCohesive[0], prob->offCohesive[1], prob->offCohesive[2], prob->offDerCohesive[0], prob->offDerCohesive[1], prob->offDerCohesive[2]));
474: PetscCall(PetscFree2(prob->T, prob->Tf));
475: PetscCall(PetscFree3(prob->u, prob->u_t, prob->u_x));
476: PetscCall(PetscFree5(prob->x, prob->basisReal, prob->basisDerReal, prob->testReal, prob->testDerReal));
477: PetscCall(PetscFree6(prob->f0, prob->f1, prob->g0, prob->g1, prob->g2, prob->g3));
478: PetscFunctionReturn(PETSC_SUCCESS);
479: }
481: static PetscErrorCode PetscDSEnlarge_Static(PetscDS prob, PetscInt NfNew)
482: {
483: PetscObject *tmpd;
484: PetscBool *tmpi;
485: PetscInt *tmpk;
486: PetscBool *tmpc;
487: PetscPointFunc *tmpup;
488: PetscSimplePointFunc *tmpexactSol, *tmpexactSol_t;
489: void **tmpexactCtx, **tmpexactCtx_t;
490: void **tmpctx;
491: PetscInt Nf = prob->Nf, f;
493: PetscFunctionBegin;
494: if (Nf >= NfNew) PetscFunctionReturn(PETSC_SUCCESS);
495: prob->setup = PETSC_FALSE;
496: PetscCall(PetscDSDestroyStructs_Static(prob));
497: PetscCall(PetscMalloc4(NfNew, &tmpd, NfNew, &tmpi, NfNew, &tmpc, NfNew, &tmpk));
498: for (f = 0; f < Nf; ++f) {
499: tmpd[f] = prob->disc[f];
500: tmpi[f] = prob->implicit[f];
501: tmpc[f] = prob->cohesive[f];
502: tmpk[f] = prob->jetDegree[f];
503: }
504: for (f = Nf; f < NfNew; ++f) {
505: tmpd[f] = NULL;
506: tmpi[f] = PETSC_TRUE, tmpc[f] = PETSC_FALSE;
507: tmpk[f] = 1;
508: }
509: PetscCall(PetscFree4(prob->disc, prob->implicit, prob->cohesive, prob->jetDegree));
510: PetscCall(PetscWeakFormSetNumFields(prob->wf, NfNew));
511: prob->Nf = NfNew;
512: prob->disc = tmpd;
513: prob->implicit = tmpi;
514: prob->cohesive = tmpc;
515: prob->jetDegree = tmpk;
516: PetscCall(PetscCalloc2(NfNew, &tmpup, NfNew, &tmpctx));
517: for (f = 0; f < Nf; ++f) tmpup[f] = prob->update[f];
518: for (f = 0; f < Nf; ++f) tmpctx[f] = prob->ctx[f];
519: for (f = Nf; f < NfNew; ++f) tmpup[f] = NULL;
520: for (f = Nf; f < NfNew; ++f) tmpctx[f] = NULL;
521: PetscCall(PetscFree2(prob->update, prob->ctx));
522: prob->update = tmpup;
523: prob->ctx = tmpctx;
524: PetscCall(PetscCalloc4(NfNew, &tmpexactSol, NfNew, &tmpexactCtx, NfNew, &tmpexactSol_t, NfNew, &tmpexactCtx_t));
525: for (f = 0; f < Nf; ++f) tmpexactSol[f] = prob->exactSol[f];
526: for (f = 0; f < Nf; ++f) tmpexactCtx[f] = prob->exactCtx[f];
527: for (f = 0; f < Nf; ++f) tmpexactSol_t[f] = prob->exactSol_t[f];
528: for (f = 0; f < Nf; ++f) tmpexactCtx_t[f] = prob->exactCtx_t[f];
529: for (f = Nf; f < NfNew; ++f) tmpexactSol[f] = NULL;
530: for (f = Nf; f < NfNew; ++f) tmpexactCtx[f] = NULL;
531: for (f = Nf; f < NfNew; ++f) tmpexactSol_t[f] = NULL;
532: for (f = Nf; f < NfNew; ++f) tmpexactCtx_t[f] = NULL;
533: PetscCall(PetscFree4(prob->exactSol, prob->exactCtx, prob->exactSol_t, prob->exactCtx_t));
534: prob->exactSol = tmpexactSol;
535: prob->exactCtx = tmpexactCtx;
536: prob->exactSol_t = tmpexactSol_t;
537: prob->exactCtx_t = tmpexactCtx_t;
538: PetscFunctionReturn(PETSC_SUCCESS);
539: }
541: /*@
542: PetscDSDestroy - Destroys a PetscDS object
544: Collective on prob
546: Input Parameter:
547: . prob - the PetscDS object to destroy
549: Level: developer
551: .seealso: `PetscDSView()`
552: @*/
553: PetscErrorCode PetscDSDestroy(PetscDS *ds)
554: {
555: PetscInt f;
557: PetscFunctionBegin;
558: if (!*ds) PetscFunctionReturn(PETSC_SUCCESS);
561: if (--((PetscObject)(*ds))->refct > 0) {
562: *ds = NULL;
563: PetscFunctionReturn(PETSC_SUCCESS);
564: }
565: ((PetscObject)(*ds))->refct = 0;
566: if ((*ds)->subprobs) {
567: PetscInt dim, d;
569: PetscCall(PetscDSGetSpatialDimension(*ds, &dim));
570: for (d = 0; d < dim; ++d) PetscCall(PetscDSDestroy(&(*ds)->subprobs[d]));
571: }
572: PetscCall(PetscFree((*ds)->subprobs));
573: PetscCall(PetscDSDestroyStructs_Static(*ds));
574: for (f = 0; f < (*ds)->Nf; ++f) PetscCall(PetscObjectDereference((*ds)->disc[f]));
575: PetscCall(PetscFree4((*ds)->disc, (*ds)->implicit, (*ds)->cohesive, (*ds)->jetDegree));
576: PetscCall(PetscWeakFormDestroy(&(*ds)->wf));
577: PetscCall(PetscFree2((*ds)->update, (*ds)->ctx));
578: PetscCall(PetscFree4((*ds)->exactSol, (*ds)->exactCtx, (*ds)->exactSol_t, (*ds)->exactCtx_t));
579: PetscTryTypeMethod((*ds), destroy);
580: PetscCall(PetscDSDestroyBoundary(*ds));
581: PetscCall(PetscFree((*ds)->constants));
582: PetscCall(PetscHeaderDestroy(ds));
583: PetscFunctionReturn(PETSC_SUCCESS);
584: }
586: /*@
587: PetscDSCreate - Creates an empty `PetscDS` object. The type can then be set with `PetscDSSetType()`.
589: Collective
591: Input Parameter:
592: . comm - The communicator for the `PetscDS` object
594: Output Parameter:
595: . ds - The `PetscDS` object
597: Level: beginner
599: .seealso: `PetscDS`, `PetscDSSetType()`, `PETSCDSBASIC`, `PetscDSType`
600: @*/
601: PetscErrorCode PetscDSCreate(MPI_Comm comm, PetscDS *ds)
602: {
603: PetscDS p;
605: PetscFunctionBegin;
607: *ds = NULL;
608: PetscCall(PetscDSInitializePackage());
610: PetscCall(PetscHeaderCreate(p, PETSCDS_CLASSID, "PetscDS", "Discrete System", "PetscDS", comm, PetscDSDestroy, PetscDSView));
612: p->Nf = 0;
613: p->setup = PETSC_FALSE;
614: p->numConstants = 0;
615: p->constants = NULL;
616: p->dimEmbed = -1;
617: p->useJacPre = PETSC_TRUE;
618: PetscCall(PetscWeakFormCreate(comm, &p->wf));
620: *ds = p;
621: PetscFunctionReturn(PETSC_SUCCESS);
622: }
624: /*@
625: PetscDSGetNumFields - Returns the number of fields in the `PetscDS`
627: Not collective
629: Input Parameter:
630: . prob - The PetscDS object
632: Output Parameter:
633: . Nf - The number of fields
635: Level: beginner
637: .seealso: `PetscDS`, `PetscDSGetSpatialDimension()`, `PetscDSCreate()`
638: @*/
639: PetscErrorCode PetscDSGetNumFields(PetscDS prob, PetscInt *Nf)
640: {
641: PetscFunctionBegin;
644: *Nf = prob->Nf;
645: PetscFunctionReturn(PETSC_SUCCESS);
646: }
648: /*@
649: PetscDSGetSpatialDimension - Returns the spatial dimension of the `PetscDS`, meaning the topological dimension of the discretizations
651: Not collective
653: Input Parameter:
654: . prob - The `PetscDS` object
656: Output Parameter:
657: . dim - The spatial dimension
659: Level: beginner
661: .seealso: `PetscDS`, `PetscDSGetCoordinateDimension()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
662: @*/
663: PetscErrorCode PetscDSGetSpatialDimension(PetscDS prob, PetscInt *dim)
664: {
665: PetscFunctionBegin;
668: *dim = 0;
669: if (prob->Nf) {
670: PetscObject obj;
671: PetscClassId id;
673: PetscCall(PetscDSGetDiscretization(prob, 0, &obj));
674: if (obj) {
675: PetscCall(PetscObjectGetClassId(obj, &id));
676: if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetSpatialDimension((PetscFE)obj, dim));
677: else if (id == PETSCFV_CLASSID) PetscCall(PetscFVGetSpatialDimension((PetscFV)obj, dim));
678: else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
679: }
680: }
681: PetscFunctionReturn(PETSC_SUCCESS);
682: }
684: /*@
685: PetscDSGetCoordinateDimension - Returns the coordinate dimension of the `PetscDS`, meaning the dimension of the space into which the discretiaztions are embedded
687: Not collective
689: Input Parameter:
690: . prob - The `PetscDS` object
692: Output Parameter:
693: . dimEmbed - The coordinate dimension
695: Level: beginner
697: .seealso: `PetscDS`, `PetscDSSetCoordinateDimension()`, `PetscDSGetSpatialDimension()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
698: @*/
699: PetscErrorCode PetscDSGetCoordinateDimension(PetscDS prob, PetscInt *dimEmbed)
700: {
701: PetscFunctionBegin;
704: PetscCheck(prob->dimEmbed >= 0, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONGSTATE, "No coordinate dimension set for this DS");
705: *dimEmbed = prob->dimEmbed;
706: PetscFunctionReturn(PETSC_SUCCESS);
707: }
709: /*@
710: PetscDSSetCoordinateDimension - Set the coordinate dimension of the `PetscDS`, meaning the dimension of the space into which the discretiaztions are embedded
712: Logically collective on prob
714: Input Parameters:
715: + prob - The `PetscDS` object
716: - dimEmbed - The coordinate dimension
718: Level: beginner
720: .seealso: `PetscDS`, `PetscDSGetCoordinateDimension()`, `PetscDSGetSpatialDimension()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
721: @*/
722: PetscErrorCode PetscDSSetCoordinateDimension(PetscDS prob, PetscInt dimEmbed)
723: {
724: PetscFunctionBegin;
726: PetscCheck(dimEmbed >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate dimension must be non-negative, not %" PetscInt_FMT, dimEmbed);
727: prob->dimEmbed = dimEmbed;
728: PetscFunctionReturn(PETSC_SUCCESS);
729: }
731: /*@
732: PetscDSIsCohesive - Returns the flag indicating that this `PetscDS` is for a cohesive cell
734: Not collective
736: Input Parameter:
737: . ds - The `PetscDS` object
739: Output Parameter:
740: . isCohesive - The flag
742: Level: developer
744: .seealso: `PetscDS`, `PetscDSGetNumCohesive()`, `PetscDSGetCohesive()`, `PetscDSSetCohesive()`, `PetscDSCreate()`
745: @*/
746: PetscErrorCode PetscDSIsCohesive(PetscDS ds, PetscBool *isCohesive)
747: {
748: PetscFunctionBegin;
751: *isCohesive = ds->isCohesive;
752: PetscFunctionReturn(PETSC_SUCCESS);
753: }
755: /*@
756: PetscDSGetNumCohesive - Returns the numer of cohesive fields, meaning those defined on the interior of a cohesive cell
758: Not collective
760: Input Parameter:
761: . ds - The `PetscDS` object
763: Output Parameter:
764: . numCohesive - The number of cohesive fields
766: Level: developer
768: .seealso: `PetscDS`, `PetscDSSetCohesive()`, `PetscDSCreate()`
769: @*/
770: PetscErrorCode PetscDSGetNumCohesive(PetscDS ds, PetscInt *numCohesive)
771: {
772: PetscInt f;
774: PetscFunctionBegin;
777: *numCohesive = 0;
778: for (f = 0; f < ds->Nf; ++f) *numCohesive += ds->cohesive[f] ? 1 : 0;
779: PetscFunctionReturn(PETSC_SUCCESS);
780: }
782: /*@
783: PetscDSGetCohesive - Returns the flag indicating that a field is cohesive, meaning it is defined on the interior of a cohesive cell
785: Not collective
787: Input Parameters:
788: + ds - The `PetscDS` object
789: - f - The field index
791: Output Parameter:
792: . isCohesive - The flag
794: Level: developer
796: .seealso: `PetscDS`, `PetscDSSetCohesive()`, `PetscDSIsCohesive()`, `PetscDSCreate()`
797: @*/
798: PetscErrorCode PetscDSGetCohesive(PetscDS ds, PetscInt f, PetscBool *isCohesive)
799: {
800: PetscFunctionBegin;
803: PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
804: *isCohesive = ds->cohesive[f];
805: PetscFunctionReturn(PETSC_SUCCESS);
806: }
808: /*@
809: PetscDSSetCohesive - Set the flag indicating that a field is cohesive, meaning it is defined on the interior of a cohesive cell
811: Not collective
813: Input Parameters:
814: + ds - The `PetscDS` object
815: . f - The field index
816: - isCohesive - The flag for a cohesive field
818: Level: developer
820: .seealso: `PetscDS`, `PetscDSGetCohesive()`, `PetscDSIsCohesive()`, `PetscDSCreate()`
821: @*/
822: PetscErrorCode PetscDSSetCohesive(PetscDS ds, PetscInt f, PetscBool isCohesive)
823: {
824: PetscInt i;
826: PetscFunctionBegin;
828: PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
829: ds->cohesive[f] = isCohesive;
830: ds->isCohesive = PETSC_FALSE;
831: for (i = 0; i < ds->Nf; ++i) ds->isCohesive = ds->isCohesive || ds->cohesive[f] ? PETSC_TRUE : PETSC_FALSE;
832: PetscFunctionReturn(PETSC_SUCCESS);
833: }
835: /*@
836: PetscDSGetTotalDimension - Returns the total size of the approximation space for this system
838: Not collective
840: Input Parameter:
841: . prob - The `PetscDS` object
843: Output Parameter:
844: . dim - The total problem dimension
846: Level: beginner
848: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
849: @*/
850: PetscErrorCode PetscDSGetTotalDimension(PetscDS prob, PetscInt *dim)
851: {
852: PetscFunctionBegin;
854: PetscCall(PetscDSSetUp(prob));
856: *dim = prob->totDim;
857: PetscFunctionReturn(PETSC_SUCCESS);
858: }
860: /*@
861: PetscDSGetTotalComponents - Returns the total number of components in this system
863: Not collective
865: Input Parameter:
866: . prob - The `PetscDS` object
868: Output Parameter:
869: . dim - The total number of components
871: Level: beginner
873: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
874: @*/
875: PetscErrorCode PetscDSGetTotalComponents(PetscDS prob, PetscInt *Nc)
876: {
877: PetscFunctionBegin;
879: PetscCall(PetscDSSetUp(prob));
881: *Nc = prob->totComp;
882: PetscFunctionReturn(PETSC_SUCCESS);
883: }
885: /*@
886: PetscDSGetDiscretization - Returns the discretization object for the given field
888: Not collective
890: Input Parameters:
891: + prob - The `PetscDS` object
892: - f - The field number
894: Output Parameter:
895: . disc - The discretization object
897: Level: beginner
899: .seealso: `PetscDS`, `PetscFE`, `PetscFV`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
900: @*/
901: PetscErrorCode PetscDSGetDiscretization(PetscDS prob, PetscInt f, PetscObject *disc)
902: {
903: PetscFunctionBeginHot;
906: PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf);
907: *disc = prob->disc[f];
908: PetscFunctionReturn(PETSC_SUCCESS);
909: }
911: /*@
912: PetscDSSetDiscretization - Sets the discretization object for the given field
914: Not collective
916: Input Parameters:
917: + prob - The `PetscDS` object
918: . f - The field number
919: - disc - The discretization object
921: Level: beginner
923: .seealso: `PetscDS`, `PetscFE`, `PetscFV`, `PetscDSGetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
924: @*/
925: PetscErrorCode PetscDSSetDiscretization(PetscDS prob, PetscInt f, PetscObject disc)
926: {
927: PetscFunctionBegin;
930: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
931: PetscCall(PetscDSEnlarge_Static(prob, f + 1));
932: PetscCall(PetscObjectDereference(prob->disc[f]));
933: prob->disc[f] = disc;
934: PetscCall(PetscObjectReference(disc));
935: if (disc) {
936: PetscClassId id;
938: PetscCall(PetscObjectGetClassId(disc, &id));
939: if (id == PETSCFE_CLASSID) {
940: PetscCall(PetscDSSetImplicit(prob, f, PETSC_TRUE));
941: } else if (id == PETSCFV_CLASSID) {
942: PetscCall(PetscDSSetImplicit(prob, f, PETSC_FALSE));
943: }
944: PetscCall(PetscDSSetJetDegree(prob, f, 1));
945: }
946: PetscFunctionReturn(PETSC_SUCCESS);
947: }
949: /*@
950: PetscDSGetWeakForm - Returns the weak form object
952: Not collective
954: Input Parameter:
955: . ds - The `PetscDS` object
957: Output Parameter:
958: . wf - The weak form object
960: Level: beginner
962: .seealso: `PetscWeakForm`, `PetscDSSetWeakForm()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
963: @*/
964: PetscErrorCode PetscDSGetWeakForm(PetscDS ds, PetscWeakForm *wf)
965: {
966: PetscFunctionBegin;
969: *wf = ds->wf;
970: PetscFunctionReturn(PETSC_SUCCESS);
971: }
973: /*@
974: PetscDSSetWeakForm - Sets the weak form object
976: Not collective
978: Input Parameters:
979: + ds - The `PetscDS` object
980: - wf - The weak form object
982: Level: beginner
984: .seealso: `PetscWeakForm`, `PetscDSGetWeakForm()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
985: @*/
986: PetscErrorCode PetscDSSetWeakForm(PetscDS ds, PetscWeakForm wf)
987: {
988: PetscFunctionBegin;
991: PetscCall(PetscObjectDereference((PetscObject)ds->wf));
992: ds->wf = wf;
993: PetscCall(PetscObjectReference((PetscObject)wf));
994: PetscCall(PetscWeakFormSetNumFields(wf, ds->Nf));
995: PetscFunctionReturn(PETSC_SUCCESS);
996: }
998: /*@
999: PetscDSAddDiscretization - Adds a discretization object
1001: Not collective
1003: Input Parameters:
1004: + prob - The `PetscDS` object
1005: - disc - The boundary discretization object
1007: Level: beginner
1009: .seealso: `PetscWeakForm`, `PetscDSGetDiscretization()`, `PetscDSSetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1010: @*/
1011: PetscErrorCode PetscDSAddDiscretization(PetscDS prob, PetscObject disc)
1012: {
1013: PetscFunctionBegin;
1014: PetscCall(PetscDSSetDiscretization(prob, prob->Nf, disc));
1015: PetscFunctionReturn(PETSC_SUCCESS);
1016: }
1018: /*@
1019: PetscDSGetQuadrature - Returns the quadrature, which must agree for all fields in the `PetscDS`
1021: Not collective
1023: Input Parameter:
1024: . prob - The `PetscDS` object
1026: Output Parameter:
1027: . q - The quadrature object
1029: Level: intermediate
1031: .seealso: `PetscDS`, `PetscQuadrature`, `PetscDSSetImplicit()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1032: @*/
1033: PetscErrorCode PetscDSGetQuadrature(PetscDS prob, PetscQuadrature *q)
1034: {
1035: PetscObject obj;
1036: PetscClassId id;
1038: PetscFunctionBegin;
1039: *q = NULL;
1040: if (!prob->Nf) PetscFunctionReturn(PETSC_SUCCESS);
1041: PetscCall(PetscDSGetDiscretization(prob, 0, &obj));
1042: PetscCall(PetscObjectGetClassId(obj, &id));
1043: if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetQuadrature((PetscFE)obj, q));
1044: else if (id == PETSCFV_CLASSID) PetscCall(PetscFVGetQuadrature((PetscFV)obj, q));
1045: else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
1046: PetscFunctionReturn(PETSC_SUCCESS);
1047: }
1049: /*@
1050: PetscDSGetImplicit - Returns the flag for implicit solve for this field. This is just a guide for `TSIMEX`
1052: Not collective
1054: Input Parameters:
1055: + prob - The `PetscDS` object
1056: - f - The field number
1058: Output Parameter:
1059: . implicit - The flag indicating what kind of solve to use for this field
1061: Level: developer
1063: .seealso: `TSIMEX`, `PetscDS`, `PetscDSSetImplicit()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1064: @*/
1065: PetscErrorCode PetscDSGetImplicit(PetscDS prob, PetscInt f, PetscBool *implicit)
1066: {
1067: PetscFunctionBegin;
1070: PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf);
1071: *implicit = prob->implicit[f];
1072: PetscFunctionReturn(PETSC_SUCCESS);
1073: }
1075: /*@
1076: PetscDSSetImplicit - Set the flag for implicit solve for this field. This is just a guide for `TSIMEX`
1078: Not collective
1080: Input Parameters:
1081: + prob - The `PetscDS` object
1082: . f - The field number
1083: - implicit - The flag indicating what kind of solve to use for this field
1085: Level: developer
1087: .seealso: `TSIMEX`, `PetscDSGetImplicit()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1088: @*/
1089: PetscErrorCode PetscDSSetImplicit(PetscDS prob, PetscInt f, PetscBool implicit)
1090: {
1091: PetscFunctionBegin;
1093: PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf);
1094: prob->implicit[f] = implicit;
1095: PetscFunctionReturn(PETSC_SUCCESS);
1096: }
1098: /*@
1099: PetscDSGetJetDegree - Returns the highest derivative for this field equation, or the k-jet that the discretization needs to tabulate.
1101: Not collective
1103: Input Parameters:
1104: + ds - The `PetscDS` object
1105: - f - The field number
1107: Output Parameter:
1108: . k - The highest derivative we need to tabulate
1110: Level: developer
1112: .seealso: `PetscDS`, `PetscDSSetJetDegree()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1113: @*/
1114: PetscErrorCode PetscDSGetJetDegree(PetscDS ds, PetscInt f, PetscInt *k)
1115: {
1116: PetscFunctionBegin;
1119: PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
1120: *k = ds->jetDegree[f];
1121: PetscFunctionReturn(PETSC_SUCCESS);
1122: }
1124: /*@
1125: PetscDSSetJetDegree - Set the highest derivative for this field equation, or the k-jet that the discretization needs to tabulate.
1127: Not collective
1129: Input Parameters:
1130: + ds - The `PetscDS` object
1131: . f - The field number
1132: - k - The highest derivative we need to tabulate
1134: Level: developer
1136: .seealso: ``PetscDS`, PetscDSGetJetDegree()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1137: @*/
1138: PetscErrorCode PetscDSSetJetDegree(PetscDS ds, PetscInt f, PetscInt k)
1139: {
1140: PetscFunctionBegin;
1142: PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
1143: ds->jetDegree[f] = k;
1144: PetscFunctionReturn(PETSC_SUCCESS);
1145: }
1147: PetscErrorCode PetscDSGetObjective(PetscDS ds, PetscInt f, void (**obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]))
1148: {
1149: PetscPointFunc *tmp;
1150: PetscInt n;
1152: PetscFunctionBegin;
1155: PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
1156: PetscCall(PetscWeakFormGetObjective(ds->wf, NULL, 0, f, 0, &n, &tmp));
1157: *obj = tmp ? tmp[0] : NULL;
1158: PetscFunctionReturn(PETSC_SUCCESS);
1159: }
1161: PetscErrorCode PetscDSSetObjective(PetscDS ds, PetscInt f, void (*obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]))
1162: {
1163: PetscFunctionBegin;
1166: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1167: PetscCall(PetscWeakFormSetIndexObjective(ds->wf, NULL, 0, f, 0, 0, obj));
1168: PetscFunctionReturn(PETSC_SUCCESS);
1169: }
1171: /*@C
1172: PetscDSGetResidual - Get the pointwise residual function for a given test field
1174: Not collective
1176: Input Parameters:
1177: + ds - The `PetscDS`
1178: - f - The test field number
1180: Output Parameters:
1181: + f0 - integrand for the test function term
1182: - f1 - integrand for the test function gradient term
1184: Calling sequence for the callbacks f0 and f1:
1185: .vb
1186: f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1187: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1188: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1189: PetscReal t, const PetscReal x[], PetscScalar f0[])
1190: .ve
1191: + dim - the spatial dimension
1192: . Nf - the number of fields
1193: . uOff - the offset into u[] and u_t[] for each field
1194: . uOff_x - the offset into u_x[] for each field
1195: . u - each field evaluated at the current point
1196: . u_t - the time derivative of each field evaluated at the current point
1197: . u_x - the gradient of each field evaluated at the current point
1198: . aOff - the offset into a[] and a_t[] for each auxiliary field
1199: . aOff_x - the offset into a_x[] for each auxiliary field
1200: . a - each auxiliary field evaluated at the current point
1201: . a_t - the time derivative of each auxiliary field evaluated at the current point
1202: . a_x - the gradient of auxiliary each field evaluated at the current point
1203: . t - current time
1204: . x - coordinates of the current point
1205: . numConstants - number of constant parameters
1206: . constants - constant parameters
1207: - f0 - output values at the current point
1209: Level: intermediate
1211: Note:
1212: We are using a first order FEM model for the weak form: \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)
1214: .seealso: `PetscDS`, `PetscDSSetResidual()`
1215: @*/
1216: PetscErrorCode PetscDSGetResidual(PetscDS ds, PetscInt f, void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
1217: {
1218: PetscPointFunc *tmp0, *tmp1;
1219: PetscInt n0, n1;
1221: PetscFunctionBegin;
1223: PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
1224: PetscCall(PetscWeakFormGetResidual(ds->wf, NULL, 0, f, 0, &n0, &tmp0, &n1, &tmp1));
1225: *f0 = tmp0 ? tmp0[0] : NULL;
1226: *f1 = tmp1 ? tmp1[0] : NULL;
1227: PetscFunctionReturn(PETSC_SUCCESS);
1228: }
1230: /*@C
1231: PetscDSSetResidual - Set the pointwise residual function for a given test field
1233: Not collective
1235: Input Parameters:
1236: + ds - The `PetscDS`
1237: . f - The test field number
1238: . f0 - integrand for the test function term
1239: - f1 - integrand for the test function gradient term
1241: Calling sequence for the callbacks f0 and f1:
1242: .vb
1243: f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1244: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1245: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1246: PetscReal t, const PetscReal x[], PetscScalar f0[])
1247: .ve
1248: + dim - the spatial dimension
1249: . Nf - the number of fields
1250: . uOff - the offset into u[] and u_t[] for each field
1251: . uOff_x - the offset into u_x[] for each field
1252: . u - each field evaluated at the current point
1253: . u_t - the time derivative of each field evaluated at the current point
1254: . u_x - the gradient of each field evaluated at the current point
1255: . aOff - the offset into a[] and a_t[] for each auxiliary field
1256: . aOff_x - the offset into a_x[] for each auxiliary field
1257: . a - each auxiliary field evaluated at the current point
1258: . a_t - the time derivative of each auxiliary field evaluated at the current point
1259: . a_x - the gradient of auxiliary each field evaluated at the current point
1260: . t - current time
1261: . x - coordinates of the current point
1262: . numConstants - number of constant parameters
1263: . constants - constant parameters
1264: - f0 - output values at the current point
1266: Level: intermediate
1268: Note:
1269: We are using a first order FEM model for the weak form: \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)
1271: .seealso: `PetscDS`, `PetscDSGetResidual()`
1272: @*/
1273: PetscErrorCode PetscDSSetResidual(PetscDS ds, PetscInt f, void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
1274: {
1275: PetscFunctionBegin;
1279: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1280: PetscCall(PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1));
1281: PetscFunctionReturn(PETSC_SUCCESS);
1282: }
1284: /*@C
1285: PetscDSGetRHSResidual - Get the pointwise RHS residual function for explicit timestepping for a given test field
1287: Not collective
1289: Input Parameters:
1290: + ds - The `PetscDS`
1291: - f - The test field number
1293: Output Parameters:
1294: + f0 - integrand for the test function term
1295: - f1 - integrand for the test function gradient term
1297: Calling sequence for the callbacks f0 and f1:
1298: .vb
1299: f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1300: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1301: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1302: PetscReal t, const PetscReal x[], PetscScalar f0[])
1303: .ve
1304: + dim - the spatial dimension
1305: . Nf - the number of fields
1306: . uOff - the offset into u[] and u_t[] for each field
1307: . uOff_x - the offset into u_x[] for each field
1308: . u - each field evaluated at the current point
1309: . u_t - the time derivative of each field evaluated at the current point
1310: . u_x - the gradient of each field evaluated at the current point
1311: . aOff - the offset into a[] and a_t[] for each auxiliary field
1312: . aOff_x - the offset into a_x[] for each auxiliary field
1313: . a - each auxiliary field evaluated at the current point
1314: . a_t - the time derivative of each auxiliary field evaluated at the current point
1315: . a_x - the gradient of auxiliary each field evaluated at the current point
1316: . t - current time
1317: . x - coordinates of the current point
1318: . numConstants - number of constant parameters
1319: . constants - constant parameters
1320: - f0 - output values at the current point
1322: Level: intermediate
1324: Note:
1325: We are using a first order FEM model for the weak form: \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)
1327: .seealso: `PetscDS`, `PetscDSSetRHSResidual()`
1328: @*/
1329: PetscErrorCode PetscDSGetRHSResidual(PetscDS ds, PetscInt f, void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
1330: {
1331: PetscPointFunc *tmp0, *tmp1;
1332: PetscInt n0, n1;
1334: PetscFunctionBegin;
1336: PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
1337: PetscCall(PetscWeakFormGetResidual(ds->wf, NULL, 0, f, 100, &n0, &tmp0, &n1, &tmp1));
1338: *f0 = tmp0 ? tmp0[0] : NULL;
1339: *f1 = tmp1 ? tmp1[0] : NULL;
1340: PetscFunctionReturn(PETSC_SUCCESS);
1341: }
1343: /*@C
1344: PetscDSSetRHSResidual - Set the pointwise residual function for explicit timestepping for a given test field
1346: Not collective
1348: Input Parameters:
1349: + ds - The `PetscDS`
1350: . f - The test field number
1351: . f0 - integrand for the test function term
1352: - f1 - integrand for the test function gradient term
1354: Clling sequence for the callbacks f0 and f1:
1355: .vb
1356: f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1357: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1358: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1359: PetscReal t, const PetscReal x[], PetscScalar f0[])
1360: .ve
1361: + dim - the spatial dimension
1362: . Nf - the number of fields
1363: . uOff - the offset into u[] and u_t[] for each field
1364: . uOff_x - the offset into u_x[] for each field
1365: . u - each field evaluated at the current point
1366: . u_t - the time derivative of each field evaluated at the current point
1367: . u_x - the gradient of each field evaluated at the current point
1368: . aOff - the offset into a[] and a_t[] for each auxiliary field
1369: . aOff_x - the offset into a_x[] for each auxiliary field
1370: . a - each auxiliary field evaluated at the current point
1371: . a_t - the time derivative of each auxiliary field evaluated at the current point
1372: . a_x - the gradient of auxiliary each field evaluated at the current point
1373: . t - current time
1374: . x - coordinates of the current point
1375: . numConstants - number of constant parameters
1376: . constants - constant parameters
1377: - f0 - output values at the current point
1379: Level: intermediate
1381: Note:
1382: We are using a first order FEM model for the weak form: \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)
1384: .seealso: `PetscDS`, `PetscDSGetResidual()`
1385: @*/
1386: PetscErrorCode PetscDSSetRHSResidual(PetscDS ds, PetscInt f, void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
1387: {
1388: PetscFunctionBegin;
1392: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1393: PetscCall(PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 100, 0, f0, 0, f1));
1394: PetscFunctionReturn(PETSC_SUCCESS);
1395: }
1397: /*@C
1398: PetscDSHasJacobian - Checks that the Jacobian functions have been set
1400: Not collective
1402: Input Parameter:
1403: . prob - The `PetscDS`
1405: Output Parameter:
1406: . hasJac - flag that pointwise function for the Jacobian has been set
1408: Level: intermediate
1410: .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`
1411: @*/
1412: PetscErrorCode PetscDSHasJacobian(PetscDS ds, PetscBool *hasJac)
1413: {
1414: PetscFunctionBegin;
1416: PetscCall(PetscWeakFormHasJacobian(ds->wf, hasJac));
1417: PetscFunctionReturn(PETSC_SUCCESS);
1418: }
1420: /*@C
1421: PetscDSGetJacobian - Get the pointwise Jacobian function for given test and basis field
1423: Not collective
1425: Input Parameters:
1426: + ds - The `PetscDS`
1427: . f - The test field number
1428: - g - The field number
1430: Output Parameters:
1431: + g0 - integrand for the test and basis function term
1432: . g1 - integrand for the test function and basis function gradient term
1433: . g2 - integrand for the test function gradient and basis function term
1434: - g3 - integrand for the test function gradient and basis function gradient term
1436: Calling sequence for the callbacks g0, g1, g2 and g3:
1437: .vb
1438: g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1439: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1440: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1441: PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])
1442: .ve
1443: + dim - the spatial dimension
1444: . Nf - the number of fields
1445: . uOff - the offset into u[] and u_t[] for each field
1446: . uOff_x - the offset into u_x[] for each field
1447: . u - each field evaluated at the current point
1448: . u_t - the time derivative of each field evaluated at the current point
1449: . u_x - the gradient of each field evaluated at the current point
1450: . aOff - the offset into a[] and a_t[] for each auxiliary field
1451: . aOff_x - the offset into a_x[] for each auxiliary field
1452: . a - each auxiliary field evaluated at the current point
1453: . a_t - the time derivative of each auxiliary field evaluated at the current point
1454: . a_x - the gradient of auxiliary each field evaluated at the current point
1455: . t - current time
1456: . u_tShift - the multiplier a for dF/dU_t
1457: . x - coordinates of the current point
1458: . numConstants - number of constant parameters
1459: . constants - constant parameters
1460: - g0 - output values at the current point
1462: Level: intermediate
1464: Note:
1465: We are using a first order FEM model for the weak form:
1466: \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
1468: .seealso: `PetscDS`, `PetscDSSetJacobian()`
1469: @*/
1470: PetscErrorCode PetscDSGetJacobian(PetscDS ds, PetscInt f, PetscInt g, void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1471: {
1472: PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
1473: PetscInt n0, n1, n2, n3;
1475: PetscFunctionBegin;
1477: PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
1478: PetscCheck(!(g < 0) && !(g >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", g, ds->Nf);
1479: PetscCall(PetscWeakFormGetJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
1480: *g0 = tmp0 ? tmp0[0] : NULL;
1481: *g1 = tmp1 ? tmp1[0] : NULL;
1482: *g2 = tmp2 ? tmp2[0] : NULL;
1483: *g3 = tmp3 ? tmp3[0] : NULL;
1484: PetscFunctionReturn(PETSC_SUCCESS);
1485: }
1487: /*@C
1488: PetscDSSetJacobian - Set the pointwise Jacobian function for given test and basis fields
1490: Not collective
1492: Input Parameters:
1493: + ds - The `PetscDS`
1494: . f - The test field number
1495: . g - The field number
1496: . g0 - integrand for the test and basis function term
1497: . g1 - integrand for the test function and basis function gradient term
1498: . g2 - integrand for the test function gradient and basis function term
1499: - g3 - integrand for the test function gradient and basis function gradient term
1501: Calling sequence for the callbacks g0, g1, g2 and g3:
1502: .vb
1503: g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1504: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1505: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1506: PetscReal t, const PetscReal x[], PetscScalar g0[])
1507: .ve
1508: + dim - the spatial dimension
1509: . Nf - the number of fields
1510: . uOff - the offset into u[] and u_t[] for each field
1511: . uOff_x - the offset into u_x[] for each field
1512: . u - each field evaluated at the current point
1513: . u_t - the time derivative of each field evaluated at the current point
1514: . u_x - the gradient of each field evaluated at the current point
1515: . aOff - the offset into a[] and a_t[] for each auxiliary field
1516: . aOff_x - the offset into a_x[] for each auxiliary field
1517: . a - each auxiliary field evaluated at the current point
1518: . a_t - the time derivative of each auxiliary field evaluated at the current point
1519: . a_x - the gradient of auxiliary each field evaluated at the current point
1520: . t - current time
1521: . u_tShift - the multiplier a for dF/dU_t
1522: . x - coordinates of the current point
1523: . numConstants - number of constant parameters
1524: . constants - constant parameters
1525: - g0 - output values at the current point
1527: Level: intermediate
1529: Note:
1530: We are using a first order FEM model for the weak form:
1531: \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
1533: .seealso: `PetscDS`, `PetscDSGetJacobian()`
1534: @*/
1535: PetscErrorCode PetscDSSetJacobian(PetscDS ds, PetscInt f, PetscInt g, void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1536: {
1537: PetscFunctionBegin;
1543: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1544: PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
1545: PetscCall(PetscWeakFormSetIndexJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
1546: PetscFunctionReturn(PETSC_SUCCESS);
1547: }
1549: /*@C
1550: PetscDSUseJacobianPreconditioner - Set whether to construct a Jacobian preconditioner
1552: Not collective
1554: Input Parameters:
1555: + prob - The `PetscDS`
1556: - useJacPre - flag that enables construction of a Jacobian preconditioner
1558: Level: intermediate
1560: .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`
1561: @*/
1562: PetscErrorCode PetscDSUseJacobianPreconditioner(PetscDS prob, PetscBool useJacPre)
1563: {
1564: PetscFunctionBegin;
1566: prob->useJacPre = useJacPre;
1567: PetscFunctionReturn(PETSC_SUCCESS);
1568: }
1570: /*@C
1571: PetscDSHasJacobianPreconditioner - Checks if a Jacobian preconditioner matrix has been set
1573: Not collective
1575: Input Parameter:
1576: . prob - The `PetscDS`
1578: Output Parameter:
1579: . hasJacPre - flag that pointwise function for Jacobian preconditioner matrix has been set
1581: Level: intermediate
1583: .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`
1584: @*/
1585: PetscErrorCode PetscDSHasJacobianPreconditioner(PetscDS ds, PetscBool *hasJacPre)
1586: {
1587: PetscFunctionBegin;
1589: *hasJacPre = PETSC_FALSE;
1590: if (!ds->useJacPre) PetscFunctionReturn(PETSC_SUCCESS);
1591: PetscCall(PetscWeakFormHasJacobianPreconditioner(ds->wf, hasJacPre));
1592: PetscFunctionReturn(PETSC_SUCCESS);
1593: }
1595: /*@C
1596: PetscDSGetJacobianPreconditioner - Get the pointwise Jacobian preconditioner function for given test and basis field. If this is missing,
1597: the system matrix is used to build the preconditioner.
1599: Not collective
1601: Input Parameters:
1602: + ds - The `PetscDS`
1603: . f - The test field number
1604: - g - The field number
1606: Output Parameters:
1607: + g0 - integrand for the test and basis function term
1608: . g1 - integrand for the test function and basis function gradient term
1609: . g2 - integrand for the test function gradient and basis function term
1610: - g3 - integrand for the test function gradient and basis function gradient term
1612: Calling sequence for the callbacks g0, g1, g2 and g3:
1613: .vb
1614: g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1615: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1616: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1617: PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])
1618: .ve
1619: + dim - the spatial dimension
1620: . Nf - the number of fields
1621: . uOff - the offset into u[] and u_t[] for each field
1622: . uOff_x - the offset into u_x[] for each field
1623: . u - each field evaluated at the current point
1624: . u_t - the time derivative of each field evaluated at the current point
1625: . u_x - the gradient of each field evaluated at the current point
1626: . aOff - the offset into a[] and a_t[] for each auxiliary field
1627: . aOff_x - the offset into a_x[] for each auxiliary field
1628: . a - each auxiliary field evaluated at the current point
1629: . a_t - the time derivative of each auxiliary field evaluated at the current point
1630: . a_x - the gradient of auxiliary each field evaluated at the current point
1631: . t - current time
1632: . u_tShift - the multiplier a for dF/dU_t
1633: . x - coordinates of the current point
1634: . numConstants - number of constant parameters
1635: . constants - constant parameters
1636: - g0 - output values at the current point
1638: Level: intermediate
1640: Note:
1641: We are using a first order FEM model for the weak form:
1642: \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
1644: .seealso: `PetscDS`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`
1645: @*/
1646: PetscErrorCode PetscDSGetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1647: {
1648: PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
1649: PetscInt n0, n1, n2, n3;
1651: PetscFunctionBegin;
1653: PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
1654: PetscCheck(!(g < 0) && !(g >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", g, ds->Nf);
1655: PetscCall(PetscWeakFormGetJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
1656: *g0 = tmp0 ? tmp0[0] : NULL;
1657: *g1 = tmp1 ? tmp1[0] : NULL;
1658: *g2 = tmp2 ? tmp2[0] : NULL;
1659: *g3 = tmp3 ? tmp3[0] : NULL;
1660: PetscFunctionReturn(PETSC_SUCCESS);
1661: }
1663: /*@C
1664: PetscDSSetJacobianPreconditioner - Set the pointwise Jacobian preconditioner function for given test and basis fields.
1665: If this is missing, the system matrix is used to build the preconditioner.
1667: Not collective
1669: Input Parameters:
1670: + ds - The `PetscDS`
1671: . f - The test field number
1672: . g - The field number
1673: . g0 - integrand for the test and basis function term
1674: . g1 - integrand for the test function and basis function gradient term
1675: . g2 - integrand for the test function gradient and basis function term
1676: - g3 - integrand for the test function gradient and basis function gradient term
1678: Calling sequence for the callbacks g0, g1, g2 and g3:
1679: .vb
1680: g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1681: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1682: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1683: PetscReal t, const PetscReal x[], PetscScalar g0[])
1684: .ve
1685: + dim - the spatial dimension
1686: . Nf - the number of fields
1687: . uOff - the offset into u[] and u_t[] for each field
1688: . uOff_x - the offset into u_x[] for each field
1689: . u - each field evaluated at the current point
1690: . u_t - the time derivative of each field evaluated at the current point
1691: . u_x - the gradient of each field evaluated at the current point
1692: . aOff - the offset into a[] and a_t[] for each auxiliary field
1693: . aOff_x - the offset into a_x[] for each auxiliary field
1694: . a - each auxiliary field evaluated at the current point
1695: . a_t - the time derivative of each auxiliary field evaluated at the current point
1696: . a_x - the gradient of auxiliary each field evaluated at the current point
1697: . t - current time
1698: . u_tShift - the multiplier a for dF/dU_t
1699: . x - coordinates of the current point
1700: . numConstants - number of constant parameters
1701: . constants - constant parameters
1702: - g0 - output values at the current point
1704: Level: intermediate
1706: Note:
1707: We are using a first order FEM model for the weak form:
1708: \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
1710: .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobian()`
1711: @*/
1712: PetscErrorCode PetscDSSetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1713: {
1714: PetscFunctionBegin;
1720: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1721: PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
1722: PetscCall(PetscWeakFormSetIndexJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
1723: PetscFunctionReturn(PETSC_SUCCESS);
1724: }
1726: /*@C
1727: PetscDSHasDynamicJacobian - Signals that a dynamic Jacobian, dF/du_t, has been set
1729: Not collective
1731: Input Parameter:
1732: . ds - The `PetscDS`
1734: Output Parameter:
1735: . hasDynJac - flag that pointwise function for dynamic Jacobian has been set
1737: Level: intermediate
1739: .seealso: `PetscDS`, `PetscDSGetDynamicJacobian()`, `PetscDSSetDynamicJacobian()`, `PetscDSGetJacobian()`
1740: @*/
1741: PetscErrorCode PetscDSHasDynamicJacobian(PetscDS ds, PetscBool *hasDynJac)
1742: {
1743: PetscFunctionBegin;
1745: PetscCall(PetscWeakFormHasDynamicJacobian(ds->wf, hasDynJac));
1746: PetscFunctionReturn(PETSC_SUCCESS);
1747: }
1749: /*@C
1750: PetscDSGetDynamicJacobian - Get the pointwise dynamic Jacobian, dF/du_t, function for given test and basis field
1752: Not collective
1754: Input Parameters:
1755: + ds - The `PetscDS`
1756: . f - The test field number
1757: - g - The field number
1759: Output Parameters:
1760: + g0 - integrand for the test and basis function term
1761: . g1 - integrand for the test function and basis function gradient term
1762: . g2 - integrand for the test function gradient and basis function term
1763: - g3 - integrand for the test function gradient and basis function gradient term
1765: Calling sequence for the callbacks g0, g1, g2 and g3:
1766: .vb
1767: g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1768: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1769: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1770: PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])
1771: .ve
1772: + dim - the spatial dimension
1773: . Nf - the number of fields
1774: . uOff - the offset into u[] and u_t[] for each field
1775: . uOff_x - the offset into u_x[] for each field
1776: . u - each field evaluated at the current point
1777: . u_t - the time derivative of each field evaluated at the current point
1778: . u_x - the gradient of each field evaluated at the current point
1779: . aOff - the offset into a[] and a_t[] for each auxiliary field
1780: . aOff_x - the offset into a_x[] for each auxiliary field
1781: . a - each auxiliary field evaluated at the current point
1782: . a_t - the time derivative of each auxiliary field evaluated at the current point
1783: . a_x - the gradient of auxiliary each field evaluated at the current point
1784: . t - current time
1785: . u_tShift - the multiplier a for dF/dU_t
1786: . x - coordinates of the current point
1787: . numConstants - number of constant parameters
1788: . constants - constant parameters
1789: - g0 - output values at the current point
1791: Level: intermediate
1793: Note:
1794: We are using a first order FEM model for the weak form:
1795: \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
1797: .seealso: `PetscDS`, `PetscDSSetJacobian()`
1798: @*/
1799: PetscErrorCode PetscDSGetDynamicJacobian(PetscDS ds, PetscInt f, PetscInt g, void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1800: {
1801: PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
1802: PetscInt n0, n1, n2, n3;
1804: PetscFunctionBegin;
1806: PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
1807: PetscCheck(!(g < 0) && !(g >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", g, ds->Nf);
1808: PetscCall(PetscWeakFormGetDynamicJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
1809: *g0 = tmp0 ? tmp0[0] : NULL;
1810: *g1 = tmp1 ? tmp1[0] : NULL;
1811: *g2 = tmp2 ? tmp2[0] : NULL;
1812: *g3 = tmp3 ? tmp3[0] : NULL;
1813: PetscFunctionReturn(PETSC_SUCCESS);
1814: }
1816: /*@C
1817: PetscDSSetDynamicJacobian - Set the pointwise dynamic Jacobian, dF/du_t, function for given test and basis fields
1819: Not collective
1821: Input Parameters:
1822: + ds - The `PetscDS`
1823: . f - The test field number
1824: . g - The field number
1825: . g0 - integrand for the test and basis function term
1826: . g1 - integrand for the test function and basis function gradient term
1827: . g2 - integrand for the test function gradient and basis function term
1828: - g3 - integrand for the test function gradient and basis function gradient term
1830: Calling sequence for the callbacks g0, g1, g2 and g3:
1831: .vb
1832: g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1833: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1834: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1835: PetscReal t, const PetscReal x[], PetscScalar g0[])
1836: .ve
1837: + dim - the spatial dimension
1838: . Nf - the number of fields
1839: . uOff - the offset into u[] and u_t[] for each field
1840: . uOff_x - the offset into u_x[] for each field
1841: . u - each field evaluated at the current point
1842: . u_t - the time derivative of each field evaluated at the current point
1843: . u_x - the gradient of each field evaluated at the current point
1844: . aOff - the offset into a[] and a_t[] for each auxiliary field
1845: . aOff_x - the offset into a_x[] for each auxiliary field
1846: . a - each auxiliary field evaluated at the current point
1847: . a_t - the time derivative of each auxiliary field evaluated at the current point
1848: . a_x - the gradient of auxiliary each field evaluated at the current point
1849: . t - current time
1850: . u_tShift - the multiplier a for dF/dU_t
1851: . x - coordinates of the current point
1852: . numConstants - number of constant parameters
1853: . constants - constant parameters
1854: - g0 - output values at the current point
1856: Level: intermediate
1858: Note:
1859: We are using a first order FEM model for the weak form:
1860: \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
1862: .seealso: `PetscDS`, `PetscDSGetJacobian()`
1863: @*/
1864: PetscErrorCode PetscDSSetDynamicJacobian(PetscDS ds, PetscInt f, PetscInt g, void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
1865: {
1866: PetscFunctionBegin;
1872: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1873: PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
1874: PetscCall(PetscWeakFormSetIndexDynamicJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
1875: PetscFunctionReturn(PETSC_SUCCESS);
1876: }
1878: /*@C
1879: PetscDSGetRiemannSolver - Returns the Riemann solver for the given field
1881: Not collective
1883: Input Parameters:
1884: + ds - The `PetscDS` object
1885: - f - The field number
1887: Output Parameter:
1888: . r - Riemann solver
1890: Calling sequence for r:
1891: .vb
1892: r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx)
1893: .ve
1894: + dim - The spatial dimension
1895: . Nf - The number of fields
1896: . x - The coordinates at a point on the interface
1897: . n - The normal vector to the interface
1898: . uL - The state vector to the left of the interface
1899: . uR - The state vector to the right of the interface
1900: . flux - output array of flux through the interface
1901: . numConstants - number of constant parameters
1902: . constants - constant parameters
1903: - ctx - optional user context
1905: Level: intermediate
1907: .seealso: `PetscDS`, `PetscDSSetRiemannSolver()`
1908: @*/
1909: PetscErrorCode PetscDSGetRiemannSolver(PetscDS ds, PetscInt f, 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))
1910: {
1911: PetscRiemannFunc *tmp;
1912: PetscInt n;
1914: PetscFunctionBegin;
1917: PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
1918: PetscCall(PetscWeakFormGetRiemannSolver(ds->wf, NULL, 0, f, 0, &n, &tmp));
1919: *r = tmp ? tmp[0] : NULL;
1920: PetscFunctionReturn(PETSC_SUCCESS);
1921: }
1923: /*@C
1924: PetscDSSetRiemannSolver - Sets the Riemann solver for the given field
1926: Not collective
1928: Input Parameters:
1929: + ds - The `PetscDS` object
1930: . f - The field number
1931: - r - Riemann solver
1933: Calling sequence for r:
1934: .vb
1935: r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx)
1936: .ve
1937: + dim - The spatial dimension
1938: . Nf - The number of fields
1939: . x - The coordinates at a point on the interface
1940: . n - The normal vector to the interface
1941: . uL - The state vector to the left of the interface
1942: . uR - The state vector to the right of the interface
1943: . flux - output array of flux through the interface
1944: . numConstants - number of constant parameters
1945: . constants - constant parameters
1946: - ctx - optional user context
1948: Level: intermediate
1950: .seealso: `PetscDS`, `PetscDSGetRiemannSolver()`
1951: @*/
1952: PetscErrorCode PetscDSSetRiemannSolver(PetscDS ds, PetscInt f, 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))
1953: {
1954: PetscFunctionBegin;
1957: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1958: PetscCall(PetscWeakFormSetIndexRiemannSolver(ds->wf, NULL, 0, f, 0, 0, r));
1959: PetscFunctionReturn(PETSC_SUCCESS);
1960: }
1962: /*@C
1963: PetscDSGetUpdate - Get the pointwise update function for a given field
1965: Not collective
1967: Input Parameters:
1968: + ds - The `PetscDS`
1969: - f - The field number
1971: Output Parameter:
1972: . update - update function
1974: Calling sequence for the callback update:
1975: .vb
1976: update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1977: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1978: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1979: PetscReal t, const PetscReal x[], PetscScalar uNew[])
1980: .ve
1981: + dim - the spatial dimension
1982: . Nf - the number of fields
1983: . uOff - the offset into u[] and u_t[] for each field
1984: . uOff_x - the offset into u_x[] for each field
1985: . u - each field evaluated at the current point
1986: . u_t - the time derivative of each field evaluated at the current point
1987: . u_x - the gradient of each field evaluated at the current point
1988: . aOff - the offset into a[] and a_t[] for each auxiliary field
1989: . aOff_x - the offset into a_x[] for each auxiliary field
1990: . a - each auxiliary field evaluated at the current point
1991: . a_t - the time derivative of each auxiliary field evaluated at the current point
1992: . a_x - the gradient of auxiliary each field evaluated at the current point
1993: . t - current time
1994: . x - coordinates of the current point
1995: - uNew - new value for field at the current point
1997: Level: intermediate
1999: .seealso: `PetscDS`, `PetscDSSetUpdate()`, `PetscDSSetResidual()`
2000: @*/
2001: PetscErrorCode PetscDSGetUpdate(PetscDS ds, PetscInt f, void (**update)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[]))
2002: {
2003: PetscFunctionBegin;
2005: PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
2006: if (update) {
2008: *update = ds->update[f];
2009: }
2010: PetscFunctionReturn(PETSC_SUCCESS);
2011: }
2013: /*@C
2014: PetscDSSetUpdate - Set the pointwise update function for a given field
2016: Not collective
2018: Input Parameters:
2019: + ds - The `PetscDS`
2020: . f - The field number
2021: - update - update function
2023: Calling sequence for the callback update:
2024: .vb
2025: update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2026: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2027: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2028: PetscReal t, const PetscReal x[], PetscScalar uNew[])
2029: .ve
2030: + dim - the spatial dimension
2031: . Nf - the number of fields
2032: . uOff - the offset into u[] and u_t[] for each field
2033: . uOff_x - the offset into u_x[] for each field
2034: . u - each field evaluated at the current point
2035: . u_t - the time derivative of each field evaluated at the current point
2036: . u_x - the gradient of each field evaluated at the current point
2037: . aOff - the offset into a[] and a_t[] for each auxiliary field
2038: . aOff_x - the offset into a_x[] for each auxiliary field
2039: . a - each auxiliary field evaluated at the current point
2040: . a_t - the time derivative of each auxiliary field evaluated at the current point
2041: . a_x - the gradient of auxiliary each field evaluated at the current point
2042: . t - current time
2043: . x - coordinates of the current point
2044: - uNew - new field values at the current point
2046: Level: intermediate
2048: .seealso: `PetscDS`, `PetscDSGetResidual()`
2049: @*/
2050: PetscErrorCode PetscDSSetUpdate(PetscDS ds, PetscInt f, void (*update)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[]))
2051: {
2052: PetscFunctionBegin;
2055: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2056: PetscCall(PetscDSEnlarge_Static(ds, f + 1));
2057: ds->update[f] = update;
2058: PetscFunctionReturn(PETSC_SUCCESS);
2059: }
2061: PetscErrorCode PetscDSGetContext(PetscDS ds, PetscInt f, void *ctx)
2062: {
2063: PetscFunctionBegin;
2065: PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
2067: *(void **)ctx = ds->ctx[f];
2068: PetscFunctionReturn(PETSC_SUCCESS);
2069: }
2071: PetscErrorCode PetscDSSetContext(PetscDS ds, PetscInt f, void *ctx)
2072: {
2073: PetscFunctionBegin;
2075: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2076: PetscCall(PetscDSEnlarge_Static(ds, f + 1));
2077: ds->ctx[f] = ctx;
2078: PetscFunctionReturn(PETSC_SUCCESS);
2079: }
2081: /*@C
2082: PetscDSGetBdResidual - Get the pointwise boundary residual function for a given test field
2084: Not collective
2086: Input Parameters:
2087: + ds - The PetscDS
2088: - f - The test field number
2090: Output Parameters:
2091: + f0 - boundary integrand for the test function term
2092: - f1 - boundary integrand for the test function gradient term
2094: Calling sequence for the callbacks f0 and f1:
2095: .vb
2096: f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2097: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2098: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2099: PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])
2100: .ve
2101: + dim - the spatial dimension
2102: . Nf - the number of fields
2103: . uOff - the offset into u[] and u_t[] for each field
2104: . uOff_x - the offset into u_x[] for each field
2105: . u - each field evaluated at the current point
2106: . u_t - the time derivative of each field evaluated at the current point
2107: . u_x - the gradient of each field evaluated at the current point
2108: . aOff - the offset into a[] and a_t[] for each auxiliary field
2109: . aOff_x - the offset into a_x[] for each auxiliary field
2110: . a - each auxiliary field evaluated at the current point
2111: . a_t - the time derivative of each auxiliary field evaluated at the current point
2112: . a_x - the gradient of auxiliary each field evaluated at the current point
2113: . t - current time
2114: . x - coordinates of the current point
2115: . n - unit normal at the current point
2116: . numConstants - number of constant parameters
2117: . constants - constant parameters
2118: - f0 - output values at the current point
2120: Level: intermediate
2122: Note:
2123: We are using a first order FEM model for the weak form:
2124: \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
2126: .seealso: `PetscDS`, `PetscDSSetBdResidual()`
2127: @*/
2128: PetscErrorCode PetscDSGetBdResidual(PetscDS ds, PetscInt f, void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
2129: {
2130: PetscBdPointFunc *tmp0, *tmp1;
2131: PetscInt n0, n1;
2133: PetscFunctionBegin;
2135: PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
2136: PetscCall(PetscWeakFormGetBdResidual(ds->wf, NULL, 0, f, 0, &n0, &tmp0, &n1, &tmp1));
2137: *f0 = tmp0 ? tmp0[0] : NULL;
2138: *f1 = tmp1 ? tmp1[0] : NULL;
2139: PetscFunctionReturn(PETSC_SUCCESS);
2140: }
2142: /*@C
2143: PetscDSSetBdResidual - Get the pointwise boundary residual function for a given test field
2145: Not collective
2147: Input Parameters:
2148: + ds - The `PetscDS`
2149: . f - The test field number
2150: . f0 - boundary integrand for the test function term
2151: - f1 - boundary integrand for the test function gradient term
2153: Calling sequence for the callbacks f0 and f1:
2154: .vb
2155: f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2156: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2157: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2158: PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])
2159: .ve
2160: + dim - the spatial dimension
2161: . Nf - the number of fields
2162: . uOff - the offset into u[] and u_t[] for each field
2163: . uOff_x - the offset into u_x[] for each field
2164: . u - each field evaluated at the current point
2165: . u_t - the time derivative of each field evaluated at the current point
2166: . u_x - the gradient of each field evaluated at the current point
2167: . aOff - the offset into a[] and a_t[] for each auxiliary field
2168: . aOff_x - the offset into a_x[] for each auxiliary field
2169: . a - each auxiliary field evaluated at the current point
2170: . a_t - the time derivative of each auxiliary field evaluated at the current point
2171: . a_x - the gradient of auxiliary each field evaluated at the current point
2172: . t - current time
2173: . x - coordinates of the current point
2174: . n - unit normal at the current point
2175: . numConstants - number of constant parameters
2176: . constants - constant parameters
2177: - f0 - output values at the current point
2179: Level: intermediate
2181: Note:
2182: We are using a first order FEM model for the weak form:
2183: \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
2185: .seealso: `PetscDS`, `PetscDSGetBdResidual()`
2186: @*/
2187: PetscErrorCode PetscDSSetBdResidual(PetscDS ds, PetscInt f, void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]))
2188: {
2189: PetscFunctionBegin;
2191: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2192: PetscCall(PetscWeakFormSetIndexBdResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1));
2193: PetscFunctionReturn(PETSC_SUCCESS);
2194: }
2196: /*@
2197: PetscDSHasBdJacobian - Indicates that boundary Jacobian functions have been set
2199: Not collective
2201: Input Parameter:
2202: . ds - The `PetscDS`
2204: Output Parameter:
2205: . hasBdJac - flag that pointwise function for the boundary Jacobian has been set
2207: Level: intermediate
2209: .seealso: `PetscDS`, `PetscDSHasJacobian()`, `PetscDSSetBdJacobian()`, `PetscDSGetBdJacobian()`
2210: @*/
2211: PetscErrorCode PetscDSHasBdJacobian(PetscDS ds, PetscBool *hasBdJac)
2212: {
2213: PetscFunctionBegin;
2216: PetscCall(PetscWeakFormHasBdJacobian(ds->wf, hasBdJac));
2217: PetscFunctionReturn(PETSC_SUCCESS);
2218: }
2220: /*@C
2221: PetscDSGetBdJacobian - Get the pointwise boundary Jacobian function for given test and basis field
2223: Not collective
2225: Input Parameters:
2226: + ds - The `PetscDS`
2227: . f - The test field number
2228: - g - The field number
2230: Output Parameters:
2231: + g0 - integrand for the test and basis function term
2232: . g1 - integrand for the test function and basis function gradient term
2233: . g2 - integrand for the test function gradient and basis function term
2234: - g3 - integrand for the test function gradient and basis function gradient term
2236: Calling sequence for the callbacks g0, g1, g2 and g3:
2237: .vb
2238: g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2239: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2240: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2241: PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[])
2242: .ve
2243: + dim - the spatial dimension
2244: . Nf - the number of fields
2245: . uOff - the offset into u[] and u_t[] for each field
2246: . uOff_x - the offset into u_x[] for each field
2247: . u - each field evaluated at the current point
2248: . u_t - the time derivative of each field evaluated at the current point
2249: . u_x - the gradient of each field evaluated at the current point
2250: . aOff - the offset into a[] and a_t[] for each auxiliary field
2251: . aOff_x - the offset into a_x[] for each auxiliary field
2252: . a - each auxiliary field evaluated at the current point
2253: . a_t - the time derivative of each auxiliary field evaluated at the current point
2254: . a_x - the gradient of auxiliary each field evaluated at the current point
2255: . t - current time
2256: . u_tShift - the multiplier a for dF/dU_t
2257: . x - coordinates of the current point
2258: . n - normal at the current point
2259: . numConstants - number of constant parameters
2260: . constants - constant parameters
2261: - g0 - output values at the current point
2263: Level: intermediate
2265: Note:
2266: We are using a first order FEM model for the weak form:
2267: \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
2269: .seealso: `PetscDS`, `PetscDSSetBdJacobian()`
2270: @*/
2271: PetscErrorCode PetscDSGetBdJacobian(PetscDS ds, PetscInt f, PetscInt g, void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2272: {
2273: PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3;
2274: PetscInt n0, n1, n2, n3;
2276: PetscFunctionBegin;
2278: PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
2279: PetscCheck(!(g < 0) && !(g >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", g, ds->Nf);
2280: PetscCall(PetscWeakFormGetBdJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
2281: *g0 = tmp0 ? tmp0[0] : NULL;
2282: *g1 = tmp1 ? tmp1[0] : NULL;
2283: *g2 = tmp2 ? tmp2[0] : NULL;
2284: *g3 = tmp3 ? tmp3[0] : NULL;
2285: PetscFunctionReturn(PETSC_SUCCESS);
2286: }
2288: /*@C
2289: PetscDSSetBdJacobian - Set the pointwise boundary Jacobian function for given test and basis field
2291: Not collective
2293: Input Parameters:
2294: + ds - The PetscDS
2295: . f - The test field number
2296: . g - The field number
2297: . g0 - integrand for the test and basis function term
2298: . g1 - integrand for the test function and basis function gradient term
2299: . g2 - integrand for the test function gradient and basis function term
2300: - g3 - integrand for the test function gradient and basis function gradient term
2302: Calling sequence for the callbacks g0, g1, g2 and g3:
2303: .vb
2304: g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2305: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2306: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2307: PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[])
2308: .ve
2309: + dim - the spatial dimension
2310: . Nf - the number of fields
2311: . uOff - the offset into u[] and u_t[] for each field
2312: . uOff_x - the offset into u_x[] for each field
2313: . u - each field evaluated at the current point
2314: . u_t - the time derivative of each field evaluated at the current point
2315: . u_x - the gradient of each field evaluated at the current point
2316: . aOff - the offset into a[] and a_t[] for each auxiliary field
2317: . aOff_x - the offset into a_x[] for each auxiliary field
2318: . a - each auxiliary field evaluated at the current point
2319: . a_t - the time derivative of each auxiliary field evaluated at the current point
2320: . a_x - the gradient of auxiliary each field evaluated at the current point
2321: . t - current time
2322: . u_tShift - the multiplier a for dF/dU_t
2323: . x - coordinates of the current point
2324: . n - normal at the current point
2325: . numConstants - number of constant parameters
2326: . constants - constant parameters
2327: - g0 - output values at the current point
2329: Level: intermediate
2331: Note:
2332: We are using a first order FEM model for the weak form:
2333: \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
2335: .seealso: `PetscDS`, `PetscDSGetBdJacobian()`
2336: @*/
2337: PetscErrorCode PetscDSSetBdJacobian(PetscDS ds, PetscInt f, PetscInt g, void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2338: {
2339: PetscFunctionBegin;
2345: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2346: PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
2347: PetscCall(PetscWeakFormSetIndexBdJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
2348: PetscFunctionReturn(PETSC_SUCCESS);
2349: }
2351: /*@
2352: PetscDSHasBdJacobianPreconditioner - Signals that boundary Jacobian preconditioner functions have been set
2354: Not collective
2356: Input Parameter:
2357: . ds - The `PetscDS`
2359: Output Parameter:
2360: . hasBdJac - flag that pointwise function for the boundary Jacobian preconditioner has been set
2362: Level: intermediate
2364: .seealso: `PetscDS`, `PetscDSHasJacobian()`, `PetscDSSetBdJacobian()`, `PetscDSGetBdJacobian()`
2365: @*/
2366: PetscErrorCode PetscDSHasBdJacobianPreconditioner(PetscDS ds, PetscBool *hasBdJacPre)
2367: {
2368: PetscFunctionBegin;
2371: PetscCall(PetscWeakFormHasBdJacobianPreconditioner(ds->wf, hasBdJacPre));
2372: PetscFunctionReturn(PETSC_SUCCESS);
2373: }
2375: /*@C
2376: PetscDSGetBdJacobianPreconditioner - Get the pointwise boundary Jacobian preconditioner function for given test and basis field
2378: Not collective
2380: Input Parameters:
2381: + ds - The `PetscDS`
2382: . f - The test field number
2383: - g - The field number
2385: Output Parameters:
2386: + g0 - integrand for the test and basis function term
2387: . g1 - integrand for the test function and basis function gradient term
2388: . g2 - integrand for the test function gradient and basis function term
2389: - g3 - integrand for the test function gradient and basis function gradient term
2391: Calling sequence for the callbacks g0, g1, g2 and g3:
2392: .vb
2393: g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2394: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2395: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2396: PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
2397: .ve
2398: + dim - the spatial dimension
2399: . Nf - the number of fields
2400: . NfAux - the number of auxiliary fields
2401: . uOff - the offset into u[] and u_t[] for each field
2402: . uOff_x - the offset into u_x[] for each field
2403: . u - each field evaluated at the current point
2404: . u_t - the time derivative of each field evaluated at the current point
2405: . u_x - the gradient of each field evaluated at the current point
2406: . aOff - the offset into a[] and a_t[] for each auxiliary field
2407: . aOff_x - the offset into a_x[] for each auxiliary field
2408: . a - each auxiliary field evaluated at the current point
2409: . a_t - the time derivative of each auxiliary field evaluated at the current point
2410: . a_x - the gradient of auxiliary each field evaluated at the current point
2411: . t - current time
2412: . u_tShift - the multiplier a for dF/dU_t
2413: . x - coordinates of the current point
2414: . n - normal at the current point
2415: . numConstants - number of constant parameters
2416: . constants - constant parameters
2417: - g0 - output values at the current point
2419: Level: intermediate
2421: Note:
2422: We are using a first order FEM model for the weak form:
2423: \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
2425: Fortran Note:
2426: This is not yet available in Fortran.
2428: .seealso: `PetscDS`, `PetscDSSetBdJacobianPreconditioner()`
2429: @*/
2430: PetscErrorCode PetscDSGetBdJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2431: {
2432: PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3;
2433: PetscInt n0, n1, n2, n3;
2435: PetscFunctionBegin;
2437: PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
2438: PetscCheck(!(g < 0) && !(g >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", g, ds->Nf);
2439: PetscCall(PetscWeakFormGetBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
2440: *g0 = tmp0 ? tmp0[0] : NULL;
2441: *g1 = tmp1 ? tmp1[0] : NULL;
2442: *g2 = tmp2 ? tmp2[0] : NULL;
2443: *g3 = tmp3 ? tmp3[0] : NULL;
2444: PetscFunctionReturn(PETSC_SUCCESS);
2445: }
2447: /*@C
2448: PetscDSSetBdJacobianPreconditioner - Set the pointwise boundary Jacobian preconditioner function for given test and basis field
2450: Not collective
2452: Input Parameters:
2453: + ds - The `PetscDS`
2454: . f - The test field number
2455: . g - The field number
2456: . g0 - integrand for the test and basis function term
2457: . g1 - integrand for the test function and basis function gradient term
2458: . g2 - integrand for the test function gradient and basis function term
2459: - g3 - integrand for the test function gradient and basis function gradient term
2461: Calling sequence for the callbacks g0, g1, g2 and g3:
2462: .vb
2463: g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2464: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2465: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2466: PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
2467: .ve
2468: + dim - the spatial dimension
2469: . Nf - the number of fields
2470: . NfAux - the number of auxiliary fields
2471: . uOff - the offset into u[] and u_t[] for each field
2472: . uOff_x - the offset into u_x[] for each field
2473: . u - each field evaluated at the current point
2474: . u_t - the time derivative of each field evaluated at the current point
2475: . u_x - the gradient of each field evaluated at the current point
2476: . aOff - the offset into a[] and a_t[] for each auxiliary field
2477: . aOff_x - the offset into a_x[] for each auxiliary field
2478: . a - each auxiliary field evaluated at the current point
2479: . a_t - the time derivative of each auxiliary field evaluated at the current point
2480: . a_x - the gradient of auxiliary each field evaluated at the current point
2481: . t - current time
2482: . u_tShift - the multiplier a for dF/dU_t
2483: . x - coordinates of the current point
2484: . n - normal at the current point
2485: . numConstants - number of constant parameters
2486: . constants - constant parameters
2487: - g0 - output values at the current point
2489: Level: intermediate
2491: Note:
2492: We are using a first order FEM model for the weak form:
2493: \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
2495: Fortran Note:
2496: This is not yet available in Fortran.
2498: .seealso: `PetscDS`, `PetscDSGetBdJacobianPreconditioner()`
2499: @*/
2500: PetscErrorCode PetscDSSetBdJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]))
2501: {
2502: PetscFunctionBegin;
2508: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2509: PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
2510: PetscCall(PetscWeakFormSetIndexBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
2511: PetscFunctionReturn(PETSC_SUCCESS);
2512: }
2514: /*@C
2515: PetscDSGetExactSolution - Get the pointwise exact solution function for a given test field
2517: Not collective
2519: Input Parameters:
2520: + prob - The PetscDS
2521: - f - The test field number
2523: Output Parameters:
2524: + exactSol - exact solution for the test field
2525: - exactCtx - exact solution context
2527: Calling sequence for the solution functions:
2528: .vb
2529: sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2530: .ve
2531: + dim - the spatial dimension
2532: . t - current time
2533: . x - coordinates of the current point
2534: . Nc - the number of field components
2535: . u - the solution field evaluated at the current point
2536: - ctx - a user context
2538: Level: intermediate
2540: .seealso: `PetscDS`, `PetscDSSetExactSolution()`, `PetscDSGetExactSolutionTimeDerivative()`
2541: @*/
2542: PetscErrorCode PetscDSGetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx)
2543: {
2544: PetscFunctionBegin;
2546: PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf);
2547: if (sol) {
2549: *sol = prob->exactSol[f];
2550: }
2551: if (ctx) {
2553: *ctx = prob->exactCtx[f];
2554: }
2555: PetscFunctionReturn(PETSC_SUCCESS);
2556: }
2558: /*@C
2559: PetscDSSetExactSolution - Set the pointwise exact solution function for a given test field
2561: Not collective
2563: Input Parameters:
2564: + prob - The `PetscDS`
2565: . f - The test field number
2566: . sol - solution function for the test fields
2567: - ctx - solution context or NULL
2569: Calling sequence for solution functions:
2570: .vb
2571: sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2572: .ve
2573: + dim - the spatial dimension
2574: . t - current time
2575: . x - coordinates of the current point
2576: . Nc - the number of field components
2577: . u - the solution field evaluated at the current point
2578: - ctx - a user context
2580: Level: intermediate
2582: .seealso: `PetscDS`, `PetscDSGetExactSolution()`
2583: @*/
2584: PetscErrorCode PetscDSSetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx)
2585: {
2586: PetscFunctionBegin;
2588: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2589: PetscCall(PetscDSEnlarge_Static(prob, f + 1));
2590: if (sol) {
2592: prob->exactSol[f] = sol;
2593: }
2594: if (ctx) {
2596: prob->exactCtx[f] = ctx;
2597: }
2598: PetscFunctionReturn(PETSC_SUCCESS);
2599: }
2601: /*@C
2602: PetscDSGetExactSolutionTimeDerivative - Get the pointwise time derivative of the exact solution function for a given test field
2604: Not collective
2606: Input Parameters:
2607: + prob - The `PetscDS`
2608: - f - The test field number
2610: Output Parameters:
2611: + exactSol - time derivative of the exact solution for the test field
2612: - exactCtx - time derivative of the exact solution context
2614: Calling sequence for the solution functions:
2615: .vb
2616: sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2617: .ve
2618: + dim - the spatial dimension
2619: . t - current time
2620: . x - coordinates of the current point
2621: . Nc - the number of field components
2622: . u - the solution field evaluated at the current point
2623: - ctx - a user context
2625: Level: intermediate
2627: .seealso: `PetscDS`, `PetscDSSetExactSolutionTimeDerivative()`, `PetscDSGetExactSolution()`
2628: @*/
2629: PetscErrorCode PetscDSGetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx)
2630: {
2631: PetscFunctionBegin;
2633: PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf);
2634: if (sol) {
2636: *sol = prob->exactSol_t[f];
2637: }
2638: if (ctx) {
2640: *ctx = prob->exactCtx_t[f];
2641: }
2642: PetscFunctionReturn(PETSC_SUCCESS);
2643: }
2645: /*@C
2646: PetscDSSetExactSolutionTimeDerivative - Set the pointwise time derivative of the exact solution function for a given test field
2648: Not collective
2650: Input Parameters:
2651: + prob - The `PetscDS`
2652: . f - The test field number
2653: . sol - time derivative of the solution function for the test fields
2654: - ctx - time derivative of the solution context or NULL
2656: Calling sequence for solution functions:
2657: .vb
2658: sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2659: .ve
2660: + dim - the spatial dimension
2661: . t - current time
2662: . x - coordinates of the current point
2663: . Nc - the number of field components
2664: . u - the solution field evaluated at the current point
2665: - ctx - a user context
2667: Level: intermediate
2669: .seealso: `PetscDS`, `PetscDSGetExactSolutionTimeDerivative()`, `PetscDSSetExactSolution()`
2670: @*/
2671: PetscErrorCode PetscDSSetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx)
2672: {
2673: PetscFunctionBegin;
2675: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2676: PetscCall(PetscDSEnlarge_Static(prob, f + 1));
2677: if (sol) {
2679: prob->exactSol_t[f] = sol;
2680: }
2681: if (ctx) {
2683: prob->exactCtx_t[f] = ctx;
2684: }
2685: PetscFunctionReturn(PETSC_SUCCESS);
2686: }
2688: /*@C
2689: PetscDSGetConstants - Returns the array of constants passed to point functions
2691: Not collective
2693: Input Parameter:
2694: . prob - The `PetscDS` object
2696: Output Parameters:
2697: + numConstants - The number of constants
2698: - constants - The array of constants, NULL if there are none
2700: Level: intermediate
2702: .seealso: `PetscDS`, `PetscDSSetConstants()`, `PetscDSCreate()`
2703: @*/
2704: PetscErrorCode PetscDSGetConstants(PetscDS prob, PetscInt *numConstants, const PetscScalar *constants[])
2705: {
2706: PetscFunctionBegin;
2708: if (numConstants) {
2710: *numConstants = prob->numConstants;
2711: }
2712: if (constants) {
2714: *constants = prob->constants;
2715: }
2716: PetscFunctionReturn(PETSC_SUCCESS);
2717: }
2719: /*@C
2720: PetscDSSetConstants - Set the array of constants passed to point functions
2722: Not collective
2724: Input Parameters:
2725: + prob - The `PetscDS` object
2726: . numConstants - The number of constants
2727: - constants - The array of constants, NULL if there are none
2729: Level: intermediate
2731: .seealso: `PetscDS`, `PetscDSGetConstants()`, `PetscDSCreate()`
2732: @*/
2733: PetscErrorCode PetscDSSetConstants(PetscDS prob, PetscInt numConstants, PetscScalar constants[])
2734: {
2735: PetscFunctionBegin;
2737: if (numConstants != prob->numConstants) {
2738: PetscCall(PetscFree(prob->constants));
2739: prob->numConstants = numConstants;
2740: if (prob->numConstants) {
2741: PetscCall(PetscMalloc1(prob->numConstants, &prob->constants));
2742: } else {
2743: prob->constants = NULL;
2744: }
2745: }
2746: if (prob->numConstants) {
2748: PetscCall(PetscArraycpy(prob->constants, constants, prob->numConstants));
2749: }
2750: PetscFunctionReturn(PETSC_SUCCESS);
2751: }
2753: /*@
2754: PetscDSGetFieldIndex - Returns the index of the given field
2756: Not collective
2758: Input Parameters:
2759: + prob - The `PetscDS` object
2760: - disc - The discretization object
2762: Output Parameter:
2763: . f - The field number
2765: Level: beginner
2767: .seealso: `PetscDS`, `PetscGetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2768: @*/
2769: PetscErrorCode PetscDSGetFieldIndex(PetscDS prob, PetscObject disc, PetscInt *f)
2770: {
2771: PetscInt g;
2773: PetscFunctionBegin;
2776: *f = -1;
2777: for (g = 0; g < prob->Nf; ++g) {
2778: if (disc == prob->disc[g]) break;
2779: }
2780: PetscCheck(g != prob->Nf, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Field not found in PetscDS.");
2781: *f = g;
2782: PetscFunctionReturn(PETSC_SUCCESS);
2783: }
2785: /*@
2786: PetscDSGetFieldSize - Returns the size of the given field in the full space basis
2788: Not collective
2790: Input Parameters:
2791: + prob - The `PetscDS` object
2792: - f - The field number
2794: Output Parameter:
2795: . size - The size
2797: Level: beginner
2799: .seealso: `PetscDS`, `PetscDSGetFieldOffset()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2800: @*/
2801: PetscErrorCode PetscDSGetFieldSize(PetscDS prob, PetscInt f, PetscInt *size)
2802: {
2803: PetscFunctionBegin;
2806: PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf);
2807: PetscCall(PetscDSSetUp(prob));
2808: *size = prob->Nb[f];
2809: PetscFunctionReturn(PETSC_SUCCESS);
2810: }
2812: /*@
2813: PetscDSGetFieldOffset - Returns the offset of the given field in the full space basis
2815: Not collective
2817: Input Parameters:
2818: + prob - The `PetscDS` object
2819: - f - The field number
2821: Output Parameter:
2822: . off - The offset
2824: Level: beginner
2826: .seealso: `PetscDS`, `PetscDSGetFieldSize()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2827: @*/
2828: PetscErrorCode PetscDSGetFieldOffset(PetscDS prob, PetscInt f, PetscInt *off)
2829: {
2830: PetscInt size, g;
2832: PetscFunctionBegin;
2835: PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf);
2836: *off = 0;
2837: for (g = 0; g < f; ++g) {
2838: PetscCall(PetscDSGetFieldSize(prob, g, &size));
2839: *off += size;
2840: }
2841: PetscFunctionReturn(PETSC_SUCCESS);
2842: }
2844: /*@
2845: PetscDSGetFieldOffsetCohesive - Returns the offset of the given field in the full space basis on a cohesive cell
2847: Not collective
2849: Input Parameters:
2850: + prob - The `PetscDS` object
2851: - f - The field number
2853: Output Parameter:
2854: . off - The offset
2856: Level: beginner
2858: .seealso: `PetscDS`, `PetscDSGetFieldSize()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2859: @*/
2860: PetscErrorCode PetscDSGetFieldOffsetCohesive(PetscDS ds, PetscInt f, PetscInt *off)
2861: {
2862: PetscInt size, g;
2864: PetscFunctionBegin;
2867: PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf);
2868: *off = 0;
2869: for (g = 0; g < f; ++g) {
2870: PetscBool cohesive;
2872: PetscCall(PetscDSGetCohesive(ds, g, &cohesive));
2873: PetscCall(PetscDSGetFieldSize(ds, g, &size));
2874: *off += cohesive ? size : size * 2;
2875: }
2876: PetscFunctionReturn(PETSC_SUCCESS);
2877: }
2879: /*@
2880: PetscDSGetDimensions - Returns the size of the approximation space for each field on an evaluation point
2882: Not collective
2884: Input Parameter:
2885: . prob - The `PetscDS` object
2887: Output Parameter:
2888: . dimensions - The number of dimensions
2890: Level: beginner
2892: .seealso: `PetscDS`, `PetscDSGetComponentOffsets()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2893: @*/
2894: PetscErrorCode PetscDSGetDimensions(PetscDS prob, PetscInt *dimensions[])
2895: {
2896: PetscFunctionBegin;
2898: PetscCall(PetscDSSetUp(prob));
2900: *dimensions = prob->Nb;
2901: PetscFunctionReturn(PETSC_SUCCESS);
2902: }
2904: /*@
2905: PetscDSGetComponents - Returns the number of components for each field on an evaluation point
2907: Not collective
2909: Input Parameter:
2910: . prob - The `PetscDS` object
2912: Output Parameter:
2913: . components - The number of components
2915: Level: beginner
2917: .seealso: `PetscDS`, `PetscDSGetComponentOffsets()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2918: @*/
2919: PetscErrorCode PetscDSGetComponents(PetscDS prob, PetscInt *components[])
2920: {
2921: PetscFunctionBegin;
2923: PetscCall(PetscDSSetUp(prob));
2925: *components = prob->Nc;
2926: PetscFunctionReturn(PETSC_SUCCESS);
2927: }
2929: /*@
2930: PetscDSGetComponentOffset - Returns the offset of the given field on an evaluation point
2932: Not collective
2934: Input Parameters:
2935: + prob - The `PetscDS` object
2936: - f - The field number
2938: Output Parameter:
2939: . off - The offset
2941: Level: beginner
2943: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2944: @*/
2945: PetscErrorCode PetscDSGetComponentOffset(PetscDS prob, PetscInt f, PetscInt *off)
2946: {
2947: PetscFunctionBegin;
2950: PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf);
2951: PetscCall(PetscDSSetUp(prob));
2952: *off = prob->off[f];
2953: PetscFunctionReturn(PETSC_SUCCESS);
2954: }
2956: /*@
2957: PetscDSGetComponentOffsets - Returns the offset of each field on an evaluation point
2959: Not collective
2961: Input Parameter:
2962: . prob - The `PetscDS` object
2964: Output Parameter:
2965: . offsets - The offsets
2967: Level: beginner
2969: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2970: @*/
2971: PetscErrorCode PetscDSGetComponentOffsets(PetscDS prob, PetscInt *offsets[])
2972: {
2973: PetscFunctionBegin;
2976: PetscCall(PetscDSSetUp(prob));
2977: *offsets = prob->off;
2978: PetscFunctionReturn(PETSC_SUCCESS);
2979: }
2981: /*@
2982: PetscDSGetComponentDerivativeOffsets - Returns the offset of each field derivative on an evaluation point
2984: Not collective
2986: Input Parameter:
2987: . prob - The `PetscDS` object
2989: Output Parameter:
2990: . offsets - The offsets
2992: Level: beginner
2994: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2995: @*/
2996: PetscErrorCode PetscDSGetComponentDerivativeOffsets(PetscDS prob, PetscInt *offsets[])
2997: {
2998: PetscFunctionBegin;
3001: PetscCall(PetscDSSetUp(prob));
3002: *offsets = prob->offDer;
3003: PetscFunctionReturn(PETSC_SUCCESS);
3004: }
3006: /*@
3007: PetscDSGetComponentOffsetsCohesive - Returns the offset of each field on an evaluation point
3009: Not collective
3011: Input Parameters:
3012: + ds - The `PetscDS` object
3013: - s - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive
3015: Output Parameter:
3016: . offsets - The offsets
3018: Level: beginner
3020: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
3021: @*/
3022: PetscErrorCode PetscDSGetComponentOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[])
3023: {
3024: PetscFunctionBegin;
3027: PetscCheck(ds->isCohesive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cohesive offsets are only valid for a cohesive DS");
3028: PetscCheck(!(s < 0) && !(s > 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cohesive side %" PetscInt_FMT " is not in [0, 2]", s);
3029: PetscCall(PetscDSSetUp(ds));
3030: *offsets = ds->offCohesive[s];
3031: PetscFunctionReturn(PETSC_SUCCESS);
3032: }
3034: /*@
3035: PetscDSGetComponentDerivativeOffsetsCohesive - Returns the offset of each field derivative on an evaluation point
3037: Not collective
3039: Input Parameters:
3040: + ds - The `PetscDS` object
3041: - s - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive
3043: Output Parameter:
3044: . offsets - The offsets
3046: Level: beginner
3048: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
3049: @*/
3050: PetscErrorCode PetscDSGetComponentDerivativeOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[])
3051: {
3052: PetscFunctionBegin;
3055: PetscCheck(ds->isCohesive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cohesive offsets are only valid for a cohesive DS");
3056: PetscCheck(!(s < 0) && !(s > 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cohesive side %" PetscInt_FMT " is not in [0, 2]", s);
3057: PetscCall(PetscDSSetUp(ds));
3058: *offsets = ds->offDerCohesive[s];
3059: PetscFunctionReturn(PETSC_SUCCESS);
3060: }
3062: /*@C
3063: PetscDSGetTabulation - Return the basis tabulation at quadrature points for the volume discretization
3065: Not collective
3067: Input Parameter:
3068: . prob - The `PetscDS` object
3070: Output Parameter:
3071: . T - The basis function and derivatives tabulation at quadrature points for each field
3073: Level: intermediate
3075: .seealso: `PetscDS`, `PetscTabulation`, `PetscDSCreate()`
3076: @*/
3077: PetscErrorCode PetscDSGetTabulation(PetscDS prob, PetscTabulation *T[])
3078: {
3079: PetscFunctionBegin;
3082: PetscCall(PetscDSSetUp(prob));
3083: *T = prob->T;
3084: PetscFunctionReturn(PETSC_SUCCESS);
3085: }
3087: /*@C
3088: PetscDSGetFaceTabulation - Return the basis tabulation at quadrature points on the faces
3090: Not collective
3092: Input Parameter:
3093: . prob - The `PetscDS` object
3095: Output Parameter:
3096: . Tf - The basis function and derivative tabulation on each local face at quadrature points for each and field
3098: Level: intermediate
3100: .seealso: `PetscTabulation`, `PetscDS`, `PetscDSGetTabulation()`, `PetscDSCreate()`
3101: @*/
3102: PetscErrorCode PetscDSGetFaceTabulation(PetscDS prob, PetscTabulation *Tf[])
3103: {
3104: PetscFunctionBegin;
3107: PetscCall(PetscDSSetUp(prob));
3108: *Tf = prob->Tf;
3109: PetscFunctionReturn(PETSC_SUCCESS);
3110: }
3112: PetscErrorCode PetscDSGetEvaluationArrays(PetscDS prob, PetscScalar **u, PetscScalar **u_t, PetscScalar **u_x)
3113: {
3114: PetscFunctionBegin;
3116: PetscCall(PetscDSSetUp(prob));
3117: if (u) {
3119: *u = prob->u;
3120: }
3121: if (u_t) {
3123: *u_t = prob->u_t;
3124: }
3125: if (u_x) {
3127: *u_x = prob->u_x;
3128: }
3129: PetscFunctionReturn(PETSC_SUCCESS);
3130: }
3132: PetscErrorCode PetscDSGetWeakFormArrays(PetscDS prob, PetscScalar **f0, PetscScalar **f1, PetscScalar **g0, PetscScalar **g1, PetscScalar **g2, PetscScalar **g3)
3133: {
3134: PetscFunctionBegin;
3136: PetscCall(PetscDSSetUp(prob));
3137: if (f0) {
3139: *f0 = prob->f0;
3140: }
3141: if (f1) {
3143: *f1 = prob->f1;
3144: }
3145: if (g0) {
3147: *g0 = prob->g0;
3148: }
3149: if (g1) {
3151: *g1 = prob->g1;
3152: }
3153: if (g2) {
3155: *g2 = prob->g2;
3156: }
3157: if (g3) {
3159: *g3 = prob->g3;
3160: }
3161: PetscFunctionReturn(PETSC_SUCCESS);
3162: }
3164: PetscErrorCode PetscDSGetWorkspace(PetscDS prob, PetscReal **x, PetscScalar **basisReal, PetscScalar **basisDerReal, PetscScalar **testReal, PetscScalar **testDerReal)
3165: {
3166: PetscFunctionBegin;
3168: PetscCall(PetscDSSetUp(prob));
3169: if (x) {
3171: *x = prob->x;
3172: }
3173: if (basisReal) {
3175: *basisReal = prob->basisReal;
3176: }
3177: if (basisDerReal) {
3179: *basisDerReal = prob->basisDerReal;
3180: }
3181: if (testReal) {
3183: *testReal = prob->testReal;
3184: }
3185: if (testDerReal) {
3187: *testDerReal = prob->testDerReal;
3188: }
3189: PetscFunctionReturn(PETSC_SUCCESS);
3190: }
3192: /*@C
3193: PetscDSAddBoundary - Add a boundary condition to the model. The pointwise functions are used to provide boundary values for essential boundary conditions.
3194: 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
3195: integrals should be performed, using the kernels from `PetscDSSetBdResidual()`.
3197: Collective on ds
3199: Input Parameters:
3200: + ds - The PetscDS object
3201: . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
3202: . name - The BC name
3203: . label - The label defining constrained points
3204: . Nv - The number of `DMLabel` values for constrained points
3205: . values - An array of label values for constrained points
3206: . field - The field to constrain
3207: . Nc - The number of constrained field components (0 will constrain all fields)
3208: . comps - An array of constrained component numbers
3209: . bcFunc - A pointwise function giving boundary values
3210: . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL
3211: - ctx - An optional user context for bcFunc
3213: Output Parameters:
3214: - bd - The boundary number
3216: Options Database Keys:
3217: + -bc_<boundary name> <num> - Overrides the boundary ids
3218: - -bc_<boundary name>_comp <num> - Overrides the boundary components
3220: Level: developer
3222: Note:
3223: Both bcFunc abd bcFunc_t will depend on the boundary condition type. If the type if `DM_BC_ESSENTIAL`, Then the calling sequence is:
3225: $ bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])
3227: If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, then the calling sequence is:
3228: .vb
3229: bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
3230: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
3231: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
3232: PetscReal time, const PetscReal x[], PetscScalar bcval[])
3233: .ve
3234: + dim - the spatial dimension
3235: . Nf - the number of fields
3236: . uOff - the offset into u[] and u_t[] for each field
3237: . uOff_x - the offset into u_x[] for each field
3238: . u - each field evaluated at the current point
3239: . u_t - the time derivative of each field evaluated at the current point
3240: . u_x - the gradient of each field evaluated at the current point
3241: . aOff - the offset into a[] and a_t[] for each auxiliary field
3242: . aOff_x - the offset into a_x[] for each auxiliary field
3243: . a - each auxiliary field evaluated at the current point
3244: . a_t - the time derivative of each auxiliary field evaluated at the current point
3245: . a_x - the gradient of auxiliary each field evaluated at the current point
3246: . t - current time
3247: . x - coordinates of the current point
3248: . numConstants - number of constant parameters
3249: . constants - constant parameters
3250: - bcval - output values at the current point
3252: .seealso: `PetscDS`, `PetscWeakForm`, `DMLabel`, `DMBoundaryConditionType`, `PetscDSAddBoundaryByName()`, `PetscDSGetBoundary()`, `PetscDSSetResidual()`, `PetscDSSetBdResidual()`
3253: @*/
3254: PetscErrorCode PetscDSAddBoundary(PetscDS ds, DMBoundaryConditionType type, const char name[], DMLabel label, PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx, PetscInt *bd)
3255: {
3256: DSBoundary head = ds->boundary, b;
3257: PetscInt n = 0;
3258: const char *lname;
3260: PetscFunctionBegin;
3268: PetscCheck(field >= 0 && field < ds->Nf, PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_OUTOFRANGE, "Field %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", field, ds->Nf);
3269: if (Nc > 0) {
3270: PetscInt *fcomps;
3271: PetscInt c;
3273: PetscCall(PetscDSGetComponents(ds, &fcomps));
3274: PetscCheck(Nc <= fcomps[field], PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_OUTOFRANGE, "Number of constrained components %" PetscInt_FMT " > %" PetscInt_FMT " components for field %" PetscInt_FMT, Nc, fcomps[field], field);
3275: for (c = 0; c < Nc; ++c) {
3276: PetscCheck(comps[c] >= 0 && comps[c] < fcomps[field], PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_OUTOFRANGE, "Constrained component[%" PetscInt_FMT "] %" PetscInt_FMT " not in [0, %" PetscInt_FMT ") components for field %" PetscInt_FMT, c, comps[c], fcomps[field], field);
3277: }
3278: }
3279: PetscCall(PetscNew(&b));
3280: PetscCall(PetscStrallocpy(name, (char **)&b->name));
3281: PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf));
3282: PetscCall(PetscWeakFormSetNumFields(b->wf, ds->Nf));
3283: PetscCall(PetscMalloc1(Nv, &b->values));
3284: if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv));
3285: PetscCall(PetscMalloc1(Nc, &b->comps));
3286: if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc));
3287: PetscCall(PetscObjectGetName((PetscObject)label, &lname));
3288: PetscCall(PetscStrallocpy(lname, (char **)&b->lname));
3289: b->type = type;
3290: b->label = label;
3291: b->Nv = Nv;
3292: b->field = field;
3293: b->Nc = Nc;
3294: b->func = bcFunc;
3295: b->func_t = bcFunc_t;
3296: b->ctx = ctx;
3297: b->next = NULL;
3298: /* Append to linked list so that we can preserve the order */
3299: if (!head) ds->boundary = b;
3300: while (head) {
3301: if (!head->next) {
3302: head->next = b;
3303: head = b;
3304: }
3305: head = head->next;
3306: ++n;
3307: }
3308: if (bd) {
3310: *bd = n;
3311: }
3312: PetscFunctionReturn(PETSC_SUCCESS);
3313: }
3315: /*@C
3316: PetscDSAddBoundaryByName - Add a boundary condition to the model. The pointwise functions are used to provide boundary values for essential boundary conditions.
3317: In FEM, they are acting upon by dual basis functionals to generate FEM coefficients which are fixed. Natural boundary conditions signal to PETSc that
3318: boundary integrals should be performed, using the kernels from `PetscDSSetBdResidual()`.
3320: Collective on ds
3322: Input Parameters:
3323: + ds - The `PetscDS` object
3324: . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
3325: . name - The BC name
3326: . lname - The naem of the label defining constrained points
3327: . Nv - The number of `DMLabel` values for constrained points
3328: . values - An array of label values for constrained points
3329: . field - The field to constrain
3330: . Nc - The number of constrained field components (0 will constrain all fields)
3331: . comps - An array of constrained component numbers
3332: . bcFunc - A pointwise function giving boundary values
3333: . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL
3334: - ctx - An optional user context for bcFunc
3336: Output Parameters:
3337: - bd - The boundary number
3339: Options Database Keys:
3340: + -bc_<boundary name> <num> - Overrides the boundary ids
3341: - -bc_<boundary name>_comp <num> - Overrides the boundary components
3343: Calling Sequence of bcFunc() and bcFunc_t():
3344: If the type is `DM_BC_ESSENTIAL`
3345: .vb
3346: bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])
3347: .ve
3348: If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value,
3349: .vb
3350: bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
3351: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
3352: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
3353: PetscReal time, const PetscReal x[], PetscScalar bcval[])
3354: .ve
3355: + dim - the spatial dimension
3356: . Nf - the number of fields
3357: . uOff - the offset into u[] and u_t[] for each field
3358: . uOff_x - the offset into u_x[] for each field
3359: . u - each field evaluated at the current point
3360: . u_t - the time derivative of each field evaluated at the current point
3361: . u_x - the gradient of each field evaluated at the current point
3362: . aOff - the offset into a[] and a_t[] for each auxiliary field
3363: . aOff_x - the offset into a_x[] for each auxiliary field
3364: . a - each auxiliary field evaluated at the current point
3365: . a_t - the time derivative of each auxiliary field evaluated at the current point
3366: . a_x - the gradient of auxiliary each field evaluated at the current point
3367: . t - current time
3368: . x - coordinates of the current point
3369: . numConstants - number of constant parameters
3370: . constants - constant parameters
3371: - bcval - output values at the current point
3373: Level: developer
3375: Note:
3376: This function should only be used with `DMFOREST` currently, since labels cannot be defined before the underlying `DMPLEX` is built.
3378: .seealso: `PetscDS`, `PetscWeakForm`, `DMLabel`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSSetResidual()`, `PetscDSSetBdResidual()`
3379: @*/
3380: PetscErrorCode PetscDSAddBoundaryByName(PetscDS ds, DMBoundaryConditionType type, const char name[], const char lname[], PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx, PetscInt *bd)
3381: {
3382: DSBoundary head = ds->boundary, b;
3383: PetscInt n = 0;
3385: PetscFunctionBegin;
3393: PetscCall(PetscNew(&b));
3394: PetscCall(PetscStrallocpy(name, (char **)&b->name));
3395: PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf));
3396: PetscCall(PetscWeakFormSetNumFields(b->wf, ds->Nf));
3397: PetscCall(PetscMalloc1(Nv, &b->values));
3398: if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv));
3399: PetscCall(PetscMalloc1(Nc, &b->comps));
3400: if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc));
3401: PetscCall(PetscStrallocpy(lname, (char **)&b->lname));
3402: b->type = type;
3403: b->label = NULL;
3404: b->Nv = Nv;
3405: b->field = field;
3406: b->Nc = Nc;
3407: b->func = bcFunc;
3408: b->func_t = bcFunc_t;
3409: b->ctx = ctx;
3410: b->next = NULL;
3411: /* Append to linked list so that we can preserve the order */
3412: if (!head) ds->boundary = b;
3413: while (head) {
3414: if (!head->next) {
3415: head->next = b;
3416: head = b;
3417: }
3418: head = head->next;
3419: ++n;
3420: }
3421: if (bd) {
3423: *bd = n;
3424: }
3425: PetscFunctionReturn(PETSC_SUCCESS);
3426: }
3428: /*@C
3429: PetscDSUpdateBoundary - Change a boundary condition for the model. The pointwise functions are used to provide boundary values for essential boundary conditions.
3430: 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
3431: should be performed, using the kernels from `PetscDSSetBdResidual()`.
3433: Input Parameters:
3434: + ds - The `PetscDS` object
3435: . bd - The boundary condition number
3436: . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
3437: . name - The BC name
3438: . label - The label defining constrained points
3439: . Nv - The number of `DMLabel` ids for constrained points
3440: . values - An array of ids for constrained points
3441: . field - The field to constrain
3442: . Nc - The number of constrained field components
3443: . comps - An array of constrained component numbers
3444: . bcFunc - A pointwise function giving boundary values
3445: . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL
3446: - ctx - An optional user context for bcFunc
3448: Level: developer
3450: Note:
3451: The boundary condition number is the order in which it was registered. The user can get the number of boundary conditions from `PetscDSGetNumBoundary()`.
3452: See `PetscDSAddBoundary()` for a description of the calling sequences for the callbacks.
3454: .seealso: `PetscDS`, `PetscWeakForm`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSGetNumBoundary()`, `DMLabel`
3455: @*/
3456: PetscErrorCode PetscDSUpdateBoundary(PetscDS ds, PetscInt bd, DMBoundaryConditionType type, const char name[], DMLabel label, PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx)
3457: {
3458: DSBoundary b = ds->boundary;
3459: PetscInt n = 0;
3461: PetscFunctionBegin;
3463: while (b) {
3464: if (n == bd) break;
3465: b = b->next;
3466: ++n;
3467: }
3468: PetscCheck(b, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bd, n);
3469: if (name) {
3470: PetscCall(PetscFree(b->name));
3471: PetscCall(PetscStrallocpy(name, (char **)&b->name));
3472: }
3473: b->type = type;
3474: if (label) {
3475: const char *name;
3477: b->label = label;
3478: PetscCall(PetscFree(b->lname));
3479: PetscCall(PetscObjectGetName((PetscObject)label, &name));
3480: PetscCall(PetscStrallocpy(name, (char **)&b->lname));
3481: }
3482: if (Nv >= 0) {
3483: b->Nv = Nv;
3484: PetscCall(PetscFree(b->values));
3485: PetscCall(PetscMalloc1(Nv, &b->values));
3486: if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv));
3487: }
3488: if (field >= 0) b->field = field;
3489: if (Nc >= 0) {
3490: b->Nc = Nc;
3491: PetscCall(PetscFree(b->comps));
3492: PetscCall(PetscMalloc1(Nc, &b->comps));
3493: if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc));
3494: }
3495: if (bcFunc) b->func = bcFunc;
3496: if (bcFunc_t) b->func_t = bcFunc_t;
3497: if (ctx) b->ctx = ctx;
3498: PetscFunctionReturn(PETSC_SUCCESS);
3499: }
3501: /*@
3502: PetscDSGetNumBoundary - Get the number of registered BC
3504: Input Parameters:
3505: . ds - The `PetscDS` object
3507: Output Parameters:
3508: . numBd - The number of BC
3510: Level: intermediate
3512: .seealso: `PetscDS`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`
3513: @*/
3514: PetscErrorCode PetscDSGetNumBoundary(PetscDS ds, PetscInt *numBd)
3515: {
3516: DSBoundary b = ds->boundary;
3518: PetscFunctionBegin;
3521: *numBd = 0;
3522: while (b) {
3523: ++(*numBd);
3524: b = b->next;
3525: }
3526: PetscFunctionReturn(PETSC_SUCCESS);
3527: }
3529: /*@C
3530: PetscDSGetBoundary - Gets a boundary condition to the model
3532: Input Parameters:
3533: + ds - The `PetscDS` object
3534: - bd - The BC number
3536: Output Parameters:
3537: + wf - The `PetscWeakForm` holding the pointwise functions
3538: . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
3539: . name - The BC name
3540: . label - The label defining constrained points
3541: . Nv - The number of `DMLabel` ids for constrained points
3542: . values - An array of ids for constrained points
3543: . field - The field to constrain
3544: . Nc - The number of constrained field components
3545: . comps - An array of constrained component numbers
3546: . bcFunc - A pointwise function giving boundary values
3547: . bcFunc_t - A pointwise function giving the time derivative of the boundary values
3548: - ctx - An optional user context for bcFunc
3550: Options Database Keys:
3551: + -bc_<boundary name> <num> - Overrides the boundary ids
3552: - -bc_<boundary name>_comp <num> - Overrides the boundary components
3554: Level: developer
3556: .seealso: `PetscDS`, `PetscWeakForm`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `DMLabel`
3557: @*/
3558: PetscErrorCode PetscDSGetBoundary(PetscDS ds, PetscInt bd, PetscWeakForm *wf, DMBoundaryConditionType *type, const char *name[], DMLabel *label, PetscInt *Nv, const PetscInt *values[], PetscInt *field, PetscInt *Nc, const PetscInt *comps[], void (**func)(void), void (**func_t)(void), void **ctx)
3559: {
3560: DSBoundary b = ds->boundary;
3561: PetscInt n = 0;
3563: PetscFunctionBegin;
3565: while (b) {
3566: if (n == bd) break;
3567: b = b->next;
3568: ++n;
3569: }
3570: PetscCheck(b, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bd, n);
3571: if (wf) {
3573: *wf = b->wf;
3574: }
3575: if (type) {
3577: *type = b->type;
3578: }
3579: if (name) {
3581: *name = b->name;
3582: }
3583: if (label) {
3585: *label = b->label;
3586: }
3587: if (Nv) {
3589: *Nv = b->Nv;
3590: }
3591: if (values) {
3593: *values = b->values;
3594: }
3595: if (field) {
3597: *field = b->field;
3598: }
3599: if (Nc) {
3601: *Nc = b->Nc;
3602: }
3603: if (comps) {
3605: *comps = b->comps;
3606: }
3607: if (func) {
3609: *func = b->func;
3610: }
3611: if (func_t) {
3613: *func_t = b->func_t;
3614: }
3615: if (ctx) {
3617: *ctx = b->ctx;
3618: }
3619: PetscFunctionReturn(PETSC_SUCCESS);
3620: }
3622: static PetscErrorCode DSBoundaryDuplicate_Internal(DSBoundary b, DSBoundary *bNew)
3623: {
3624: PetscFunctionBegin;
3625: PetscCall(PetscNew(bNew));
3626: PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &(*bNew)->wf));
3627: PetscCall(PetscWeakFormCopy(b->wf, (*bNew)->wf));
3628: PetscCall(PetscStrallocpy(b->name, (char **)&((*bNew)->name)));
3629: PetscCall(PetscStrallocpy(b->lname, (char **)&((*bNew)->lname)));
3630: (*bNew)->type = b->type;
3631: (*bNew)->label = b->label;
3632: (*bNew)->Nv = b->Nv;
3633: PetscCall(PetscMalloc1(b->Nv, &(*bNew)->values));
3634: PetscCall(PetscArraycpy((*bNew)->values, b->values, b->Nv));
3635: (*bNew)->field = b->field;
3636: (*bNew)->Nc = b->Nc;
3637: PetscCall(PetscMalloc1(b->Nc, &(*bNew)->comps));
3638: PetscCall(PetscArraycpy((*bNew)->comps, b->comps, b->Nc));
3639: (*bNew)->func = b->func;
3640: (*bNew)->func_t = b->func_t;
3641: (*bNew)->ctx = b->ctx;
3642: PetscFunctionReturn(PETSC_SUCCESS);
3643: }
3645: /*@
3646: PetscDSCopyBoundary - Copy all boundary condition objects to the new problem
3648: Not collective
3650: Input Parameters:
3651: + ds - The source `PetscDS` object
3652: . numFields - The number of selected fields, or `PETSC_DEFAULT` for all fields
3653: - fields - The selected fields, or NULL for all fields
3655: Output Parameter:
3656: . newds - The target `PetscDS`, now with a copy of the boundary conditions
3658: Level: intermediate
3660: .seealso: `PetscDS`, `DMBoundary`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3661: @*/
3662: PetscErrorCode PetscDSCopyBoundary(PetscDS ds, PetscInt numFields, const PetscInt fields[], PetscDS newds)
3663: {
3664: DSBoundary b, *lastnext;
3666: PetscFunctionBegin;
3669: if (ds == newds) PetscFunctionReturn(PETSC_SUCCESS);
3670: PetscCall(PetscDSDestroyBoundary(newds));
3671: lastnext = &(newds->boundary);
3672: for (b = ds->boundary; b; b = b->next) {
3673: DSBoundary bNew;
3674: PetscInt fieldNew = -1;
3676: if (numFields > 0 && fields) {
3677: PetscInt f;
3679: for (f = 0; f < numFields; ++f)
3680: if (b->field == fields[f]) break;
3681: if (f == numFields) continue;
3682: fieldNew = f;
3683: }
3684: PetscCall(DSBoundaryDuplicate_Internal(b, &bNew));
3685: bNew->field = fieldNew < 0 ? b->field : fieldNew;
3686: *lastnext = bNew;
3687: lastnext = &(bNew->next);
3688: }
3689: PetscFunctionReturn(PETSC_SUCCESS);
3690: }
3692: /*@
3693: PetscDSDestroyBoundary - Remove all `DMBoundary` objects from the `PetscDS`
3695: Not collective
3697: Input Parameter:
3698: . ds - The `PetscDS` object
3700: Level: intermediate
3702: .seealso: `PetscDS`, `DMBoundary`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`
3703: @*/
3704: PetscErrorCode PetscDSDestroyBoundary(PetscDS ds)
3705: {
3706: DSBoundary next = ds->boundary;
3708: PetscFunctionBegin;
3709: while (next) {
3710: DSBoundary b = next;
3712: next = b->next;
3713: PetscCall(PetscWeakFormDestroy(&b->wf));
3714: PetscCall(PetscFree(b->name));
3715: PetscCall(PetscFree(b->lname));
3716: PetscCall(PetscFree(b->values));
3717: PetscCall(PetscFree(b->comps));
3718: PetscCall(PetscFree(b));
3719: }
3720: PetscFunctionReturn(PETSC_SUCCESS);
3721: }
3723: /*@
3724: PetscDSSelectDiscretizations - Copy discretizations to the new problem with different field layout
3726: Not collective
3728: Input Parameters:
3729: + prob - The `PetscDS` object
3730: . numFields - Number of new fields
3731: - fields - Old field number for each new field
3733: Output Parameter:
3734: . newprob - The `PetscDS` copy
3736: Level: intermediate
3738: .seealso: `PetscDS`, `PetscDSSelectEquations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3739: @*/
3740: PetscErrorCode PetscDSSelectDiscretizations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob)
3741: {
3742: PetscInt Nf, Nfn, fn;
3744: PetscFunctionBegin;
3748: PetscCall(PetscDSGetNumFields(prob, &Nf));
3749: PetscCall(PetscDSGetNumFields(newprob, &Nfn));
3750: numFields = numFields < 0 ? Nf : numFields;
3751: for (fn = 0; fn < numFields; ++fn) {
3752: const PetscInt f = fields ? fields[fn] : fn;
3753: PetscObject disc;
3755: if (f >= Nf) continue;
3756: PetscCall(PetscDSGetDiscretization(prob, f, &disc));
3757: PetscCall(PetscDSSetDiscretization(newprob, fn, disc));
3758: }
3759: PetscFunctionReturn(PETSC_SUCCESS);
3760: }
3762: /*@
3763: PetscDSSelectEquations - Copy pointwise function pointers to the new problem with different field layout
3765: Not collective
3767: Input Parameters:
3768: + prob - The `PetscDS` object
3769: . numFields - Number of new fields
3770: - fields - Old field number for each new field
3772: Output Parameter:
3773: . newprob - The `PetscDS` copy
3775: Level: intermediate
3777: .seealso: `PetscDS`, `PetscDSSelectDiscretizations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3778: @*/
3779: PetscErrorCode PetscDSSelectEquations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob)
3780: {
3781: PetscInt Nf, Nfn, fn, gn;
3783: PetscFunctionBegin;
3787: PetscCall(PetscDSGetNumFields(prob, &Nf));
3788: PetscCall(PetscDSGetNumFields(newprob, &Nfn));
3789: PetscCheck(numFields <= Nfn, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_SIZ, "Number of fields %" PetscInt_FMT " to transfer must not be greater then the total number of fields %" PetscInt_FMT, numFields, Nfn);
3790: for (fn = 0; fn < numFields; ++fn) {
3791: const PetscInt f = fields ? fields[fn] : fn;
3792: PetscPointFunc obj;
3793: PetscPointFunc f0, f1;
3794: PetscBdPointFunc f0Bd, f1Bd;
3795: PetscRiemannFunc r;
3797: if (f >= Nf) continue;
3798: PetscCall(PetscDSGetObjective(prob, f, &obj));
3799: PetscCall(PetscDSGetResidual(prob, f, &f0, &f1));
3800: PetscCall(PetscDSGetBdResidual(prob, f, &f0Bd, &f1Bd));
3801: PetscCall(PetscDSGetRiemannSolver(prob, f, &r));
3802: PetscCall(PetscDSSetObjective(newprob, fn, obj));
3803: PetscCall(PetscDSSetResidual(newprob, fn, f0, f1));
3804: PetscCall(PetscDSSetBdResidual(newprob, fn, f0Bd, f1Bd));
3805: PetscCall(PetscDSSetRiemannSolver(newprob, fn, r));
3806: for (gn = 0; gn < numFields; ++gn) {
3807: const PetscInt g = fields ? fields[gn] : gn;
3808: PetscPointJac g0, g1, g2, g3;
3809: PetscPointJac g0p, g1p, g2p, g3p;
3810: PetscBdPointJac g0Bd, g1Bd, g2Bd, g3Bd;
3812: if (g >= Nf) continue;
3813: PetscCall(PetscDSGetJacobian(prob, f, g, &g0, &g1, &g2, &g3));
3814: PetscCall(PetscDSGetJacobianPreconditioner(prob, f, g, &g0p, &g1p, &g2p, &g3p));
3815: PetscCall(PetscDSGetBdJacobian(prob, f, g, &g0Bd, &g1Bd, &g2Bd, &g3Bd));
3816: PetscCall(PetscDSSetJacobian(newprob, fn, gn, g0, g1, g2, g3));
3817: PetscCall(PetscDSSetJacobianPreconditioner(newprob, fn, gn, g0p, g1p, g2p, g3p));
3818: PetscCall(PetscDSSetBdJacobian(newprob, fn, gn, g0Bd, g1Bd, g2Bd, g3Bd));
3819: }
3820: }
3821: PetscFunctionReturn(PETSC_SUCCESS);
3822: }
3824: /*@
3825: PetscDSCopyEquations - Copy all pointwise function pointers to another `PetscDS`
3827: Not collective
3829: Input Parameter:
3830: . prob - The `PetscDS` object
3832: Output Parameter:
3833: . newprob - The `PetscDS` copy
3835: Level: intermediate
3837: .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3838: @*/
3839: PetscErrorCode PetscDSCopyEquations(PetscDS prob, PetscDS newprob)
3840: {
3841: PetscWeakForm wf, newwf;
3842: PetscInt Nf, Ng;
3844: PetscFunctionBegin;
3847: PetscCall(PetscDSGetNumFields(prob, &Nf));
3848: PetscCall(PetscDSGetNumFields(newprob, &Ng));
3849: PetscCheck(Nf == Ng, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_SIZ, "Number of fields must match %" PetscInt_FMT " != %" PetscInt_FMT, Nf, Ng);
3850: PetscCall(PetscDSGetWeakForm(prob, &wf));
3851: PetscCall(PetscDSGetWeakForm(newprob, &newwf));
3852: PetscCall(PetscWeakFormCopy(wf, newwf));
3853: PetscFunctionReturn(PETSC_SUCCESS);
3854: }
3856: /*@
3857: PetscDSCopyConstants - Copy all constants to another `PetscDS`
3859: Not collective
3861: Input Parameter:
3862: . prob - The `PetscDS` object
3864: Output Parameter:
3865: . newprob - The `PetscDS` copy
3867: Level: intermediate
3869: .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3870: @*/
3871: PetscErrorCode PetscDSCopyConstants(PetscDS prob, PetscDS newprob)
3872: {
3873: PetscInt Nc;
3874: const PetscScalar *constants;
3876: PetscFunctionBegin;
3879: PetscCall(PetscDSGetConstants(prob, &Nc, &constants));
3880: PetscCall(PetscDSSetConstants(newprob, Nc, (PetscScalar *)constants));
3881: PetscFunctionReturn(PETSC_SUCCESS);
3882: }
3884: /*@
3885: PetscDSCopyExactSolutions - Copy all exact solutions to another `PetscDS`
3887: Not collective
3889: Input Parameter:
3890: . ds - The `PetscDS` object
3892: Output Parameter:
3893: . newds - The `PetscDS` copy
3895: Level: intermediate
3897: .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3898: @*/
3899: PetscErrorCode PetscDSCopyExactSolutions(PetscDS ds, PetscDS newds)
3900: {
3901: PetscSimplePointFunc sol;
3902: void *ctx;
3903: PetscInt Nf, f;
3905: PetscFunctionBegin;
3908: PetscCall(PetscDSGetNumFields(ds, &Nf));
3909: for (f = 0; f < Nf; ++f) {
3910: PetscCall(PetscDSGetExactSolution(ds, f, &sol, &ctx));
3911: PetscCall(PetscDSSetExactSolution(newds, f, sol, ctx));
3912: PetscCall(PetscDSGetExactSolutionTimeDerivative(ds, f, &sol, &ctx));
3913: PetscCall(PetscDSSetExactSolutionTimeDerivative(newds, f, sol, ctx));
3914: }
3915: PetscFunctionReturn(PETSC_SUCCESS);
3916: }
3918: PetscErrorCode PetscDSGetHeightSubspace(PetscDS prob, PetscInt height, PetscDS *subprob)
3919: {
3920: PetscInt dim, Nf, f;
3922: PetscFunctionBegin;
3925: if (height == 0) {
3926: *subprob = prob;
3927: PetscFunctionReturn(PETSC_SUCCESS);
3928: }
3929: PetscCall(PetscDSGetNumFields(prob, &Nf));
3930: PetscCall(PetscDSGetSpatialDimension(prob, &dim));
3931: PetscCheck(height <= dim, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_OUTOFRANGE, "DS can only handle height in [0, %" PetscInt_FMT "], not %" PetscInt_FMT, dim, height);
3932: if (!prob->subprobs) PetscCall(PetscCalloc1(dim, &prob->subprobs));
3933: if (!prob->subprobs[height - 1]) {
3934: PetscInt cdim;
3936: PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)prob), &prob->subprobs[height - 1]));
3937: PetscCall(PetscDSGetCoordinateDimension(prob, &cdim));
3938: PetscCall(PetscDSSetCoordinateDimension(prob->subprobs[height - 1], cdim));
3939: for (f = 0; f < Nf; ++f) {
3940: PetscFE subfe;
3941: PetscObject obj;
3942: PetscClassId id;
3944: PetscCall(PetscDSGetDiscretization(prob, f, &obj));
3945: PetscCall(PetscObjectGetClassId(obj, &id));
3946: if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetHeightSubspace((PetscFE)obj, height, &subfe));
3947: else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unsupported discretization type for field %" PetscInt_FMT, f);
3948: PetscCall(PetscDSSetDiscretization(prob->subprobs[height - 1], f, (PetscObject)subfe));
3949: }
3950: }
3951: *subprob = prob->subprobs[height - 1];
3952: PetscFunctionReturn(PETSC_SUCCESS);
3953: }
3955: PetscErrorCode PetscDSGetDiscType_Internal(PetscDS ds, PetscInt f, PetscDiscType *disctype)
3956: {
3957: PetscObject obj;
3958: PetscClassId id;
3959: PetscInt Nf;
3961: PetscFunctionBegin;
3964: *disctype = PETSC_DISC_NONE;
3965: PetscCall(PetscDSGetNumFields(ds, &Nf));
3966: PetscCheck(f < Nf, PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_SIZ, "Field %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf);
3967: PetscCall(PetscDSGetDiscretization(ds, f, &obj));
3968: if (obj) {
3969: PetscCall(PetscObjectGetClassId(obj, &id));
3970: if (id == PETSCFE_CLASSID) *disctype = PETSC_DISC_FE;
3971: else *disctype = PETSC_DISC_FV;
3972: }
3973: PetscFunctionReturn(PETSC_SUCCESS);
3974: }
3976: static PetscErrorCode PetscDSDestroy_Basic(PetscDS ds)
3977: {
3978: PetscFunctionBegin;
3979: PetscCall(PetscFree(ds->data));
3980: PetscFunctionReturn(PETSC_SUCCESS);
3981: }
3983: static PetscErrorCode PetscDSInitialize_Basic(PetscDS ds)
3984: {
3985: PetscFunctionBegin;
3986: ds->ops->setfromoptions = NULL;
3987: ds->ops->setup = NULL;
3988: ds->ops->view = NULL;
3989: ds->ops->destroy = PetscDSDestroy_Basic;
3990: PetscFunctionReturn(PETSC_SUCCESS);
3991: }
3993: /*MC
3994: PETSCDSBASIC = "basic" - A discrete system with pointwise residual and boundary residual functions
3996: Level: intermediate
3998: .seealso: `PetscDSType`, `PetscDSCreate()`, `PetscDSSetType()`
3999: M*/
4001: PETSC_EXTERN PetscErrorCode PetscDSCreate_Basic(PetscDS ds)
4002: {
4003: PetscDS_Basic *b;
4005: PetscFunctionBegin;
4007: PetscCall(PetscNew(&b));
4008: ds->data = b;
4010: PetscCall(PetscDSInitialize_Basic(ds));
4011: PetscFunctionReturn(PETSC_SUCCESS);
4012: }