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; No Fortran Support
26: Input Parameters:
27: + sname - The name of a new user-defined creation routine
28: - function - 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: .seealso: `PetscDSType`, `PetscDS`, `PetscDSRegisterAll()`, `PetscDSRegisterDestroy()`
51: @*/
52: PetscErrorCode PetscDSRegister(const char sname[], PetscErrorCode (*function)(PetscDS))
53: {
54: PetscFunctionBegin;
55: PetscCall(PetscFunctionListAdd(&PetscDSList, sname, function));
56: PetscFunctionReturn(PETSC_SUCCESS);
57: }
59: /*@C
60: PetscDSSetType - Builds a particular `PetscDS`
62: Collective; No Fortran Support
64: Input Parameters:
65: + prob - The `PetscDS` object
66: - name - The `PetscDSType`
68: Options Database Key:
69: . -petscds_type <type> - Sets the PetscDS type; use -help for a list of available types
71: Level: intermediate
73: .seealso: `PetscDSType`, `PetscDS`, `PetscDSGetType()`, `PetscDSCreate()`
74: @*/
75: PetscErrorCode PetscDSSetType(PetscDS prob, PetscDSType name)
76: {
77: PetscErrorCode (*r)(PetscDS);
78: PetscBool match;
80: PetscFunctionBegin;
82: PetscCall(PetscObjectTypeCompare((PetscObject)prob, name, &match));
83: if (match) PetscFunctionReturn(PETSC_SUCCESS);
85: PetscCall(PetscDSRegisterAll());
86: PetscCall(PetscFunctionListFind(PetscDSList, name, &r));
87: PetscCheck(r, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDS type: %s", name);
89: PetscTryTypeMethod(prob, destroy);
90: prob->ops->destroy = NULL;
92: PetscCall((*r)(prob));
93: PetscCall(PetscObjectChangeTypeName((PetscObject)prob, name));
94: PetscFunctionReturn(PETSC_SUCCESS);
95: }
97: /*@C
98: PetscDSGetType - Gets the `PetscDSType` name (as a string) from the `PetscDS`
100: Not Collective; No Fortran Support
102: Input Parameter:
103: . prob - The `PetscDS`
105: Output Parameter:
106: . name - The `PetscDSType` name
108: Level: intermediate
110: .seealso: `PetscDSType`, `PetscDS`, `PetscDSSetType()`, `PetscDSCreate()`
111: @*/
112: PetscErrorCode PetscDSGetType(PetscDS prob, PetscDSType *name)
113: {
114: PetscFunctionBegin;
117: PetscCall(PetscDSRegisterAll());
118: *name = ((PetscObject)prob)->type_name;
119: PetscFunctionReturn(PETSC_SUCCESS);
120: }
122: static PetscErrorCode PetscDSView_Ascii(PetscDS ds, PetscViewer viewer)
123: {
124: PetscViewerFormat format;
125: const PetscScalar *constants;
126: PetscInt Nf, numConstants, f;
128: PetscFunctionBegin;
129: PetscCall(PetscDSGetNumFields(ds, &Nf));
130: PetscCall(PetscViewerGetFormat(viewer, &format));
131: PetscCall(PetscViewerASCIIPrintf(viewer, "Discrete System with %" PetscInt_FMT " fields\n", Nf));
132: PetscCall(PetscViewerASCIIPushTab(viewer));
133: PetscCall(PetscViewerASCIIPrintf(viewer, " cell total dim %" PetscInt_FMT " total comp %" PetscInt_FMT "\n", ds->totDim, ds->totComp));
134: if (ds->isCohesive) PetscCall(PetscViewerASCIIPrintf(viewer, " cohesive cell\n"));
135: for (f = 0; f < Nf; ++f) {
136: DSBoundary b;
137: PetscObject obj;
138: PetscClassId id;
139: PetscQuadrature q;
140: const char *name;
141: PetscInt Nc, Nq, Nqc;
143: PetscCall(PetscDSGetDiscretization(ds, f, &obj));
144: PetscCall(PetscObjectGetClassId(obj, &id));
145: PetscCall(PetscObjectGetName(obj, &name));
146: PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s", name ? name : "<unknown>"));
147: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
148: if (id == PETSCFE_CLASSID) {
149: PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
150: PetscCall(PetscFEGetQuadrature((PetscFE)obj, &q));
151: PetscCall(PetscViewerASCIIPrintf(viewer, " FEM"));
152: } else if (id == PETSCFV_CLASSID) {
153: PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc));
154: PetscCall(PetscFVGetQuadrature((PetscFV)obj, &q));
155: PetscCall(PetscViewerASCIIPrintf(viewer, " FVM"));
156: } else SETERRQ(PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, f);
157: if (Nc > 1) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " components", Nc));
158: else PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " component ", Nc));
159: if (ds->implicit[f]) PetscCall(PetscViewerASCIIPrintf(viewer, " (implicit)"));
160: else PetscCall(PetscViewerASCIIPrintf(viewer, " (explicit)"));
161: if (q) {
162: PetscCall(PetscQuadratureGetData(q, NULL, &Nqc, &Nq, NULL, NULL));
163: PetscCall(PetscViewerASCIIPrintf(viewer, " (Nq %" PetscInt_FMT " Nqc %" PetscInt_FMT ")", Nq, Nqc));
164: }
165: PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "-jet", ds->jetDegree[f]));
166: PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
167: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
168: PetscCall(PetscViewerASCIIPushTab(viewer));
169: if (id == PETSCFE_CLASSID) PetscCall(PetscFEView((PetscFE)obj, viewer));
170: else if (id == PETSCFV_CLASSID) PetscCall(PetscFVView((PetscFV)obj, viewer));
171: PetscCall(PetscViewerASCIIPopTab(viewer));
173: for (b = ds->boundary; b; b = b->next) {
174: char *name;
175: PetscInt c, i;
177: if (b->field != f) continue;
178: PetscCall(PetscViewerASCIIPushTab(viewer));
179: PetscCall(PetscViewerASCIIPrintf(viewer, "Boundary %s (%s) %s\n", b->name, b->lname, DMBoundaryConditionTypes[b->type]));
180: if (!b->Nc) {
181: PetscCall(PetscViewerASCIIPrintf(viewer, " all components\n"));
182: } else {
183: PetscCall(PetscViewerASCIIPrintf(viewer, " components: "));
184: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
185: for (c = 0; c < b->Nc; ++c) {
186: if (c > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
187: PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT, b->comps[c]));
188: }
189: PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
190: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
191: }
192: PetscCall(PetscViewerASCIIPrintf(viewer, " values: "));
193: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
194: for (i = 0; i < b->Nv; ++i) {
195: if (i > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
196: PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT, b->values[i]));
197: }
198: PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
199: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
200: #if defined(__clang__)
201: PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN("-Wformat-pedantic");
202: #elif defined(__GNUC__) || defined(__GNUG__)
203: PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN("-Wformat");
204: #endif
205: if (b->func) {
206: PetscCall(PetscDLAddr(b->func, &name));
207: if (name) PetscCall(PetscViewerASCIIPrintf(viewer, " func: %s\n", name));
208: else PetscCall(PetscViewerASCIIPrintf(viewer, " func: %p\n", b->func));
209: PetscCall(PetscFree(name));
210: }
211: if (b->func_t) {
212: PetscCall(PetscDLAddr(b->func_t, &name));
213: if (name) PetscCall(PetscViewerASCIIPrintf(viewer, " func_t: %s\n", name));
214: else PetscCall(PetscViewerASCIIPrintf(viewer, " func_t: %p\n", b->func_t));
215: PetscCall(PetscFree(name));
216: }
217: PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END();
218: PetscCall(PetscWeakFormView(b->wf, viewer));
219: PetscCall(PetscViewerASCIIPopTab(viewer));
220: }
221: }
222: PetscCall(PetscDSGetConstants(ds, &numConstants, &constants));
223: if (numConstants) {
224: PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " constants\n", numConstants));
225: PetscCall(PetscViewerASCIIPushTab(viewer));
226: for (f = 0; f < numConstants; ++f) PetscCall(PetscViewerASCIIPrintf(viewer, "%g\n", (double)PetscRealPart(constants[f])));
227: PetscCall(PetscViewerASCIIPopTab(viewer));
228: }
229: PetscCall(PetscWeakFormView(ds->wf, viewer));
230: PetscCall(PetscViewerASCIIPopTab(viewer));
231: PetscFunctionReturn(PETSC_SUCCESS);
232: }
234: /*@C
235: PetscDSViewFromOptions - View a `PetscDS` based on values in the options database
237: Collective
239: Input Parameters:
240: + A - the `PetscDS` object
241: . obj - Optional object that provides the options prefix used in the search
242: - name - command line option
244: Level: intermediate
246: .seealso: `PetscDSType`, `PetscDS`, `PetscDSView()`, `PetscObjectViewFromOptions()`, `PetscDSCreate()`
247: @*/
248: PetscErrorCode PetscDSViewFromOptions(PetscDS A, PetscObject obj, const char name[])
249: {
250: PetscFunctionBegin;
252: PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
253: PetscFunctionReturn(PETSC_SUCCESS);
254: }
256: /*@C
257: PetscDSView - Views a `PetscDS`
259: Collective
261: Input Parameters:
262: + prob - the `PetscDS` object to view
263: - v - the viewer
265: Level: developer
267: .seealso: `PetscDSType`, `PetscDS`, `PetscViewer`, `PetscDSDestroy()`, `PetscDSViewFromOptions()`
268: @*/
269: PetscErrorCode PetscDSView(PetscDS prob, PetscViewer v)
270: {
271: PetscBool iascii;
273: PetscFunctionBegin;
275: if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)prob), &v));
277: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii));
278: if (iascii) PetscCall(PetscDSView_Ascii(prob, v));
279: PetscTryTypeMethod(prob, view, v);
280: PetscFunctionReturn(PETSC_SUCCESS);
281: }
283: /*@
284: PetscDSSetFromOptions - sets parameters in a `PetscDS` from the options database
286: Collective
288: Input Parameter:
289: . prob - the `PetscDS` object to set options for
291: Options Database Keys:
292: + -petscds_type <type> - Set the `PetscDS` type
293: . -petscds_view <view opt> - View the `PetscDS`
294: . -petscds_jac_pre - Turn formation of a separate Jacobian preconditioner on or off
295: . -bc_<name> <ids> - Specify a list of label ids for a boundary condition
296: - -bc_<name>_comp <comps> - Specify a list of field components to constrain for a boundary condition
298: Level: intermediate
300: .seealso: `PetscDS`, `PetscDSView()`
301: @*/
302: PetscErrorCode PetscDSSetFromOptions(PetscDS prob)
303: {
304: DSBoundary b;
305: const char *defaultType;
306: char name[256];
307: PetscBool flg;
309: PetscFunctionBegin;
311: if (!((PetscObject)prob)->type_name) {
312: defaultType = PETSCDSBASIC;
313: } else {
314: defaultType = ((PetscObject)prob)->type_name;
315: }
316: PetscCall(PetscDSRegisterAll());
318: PetscObjectOptionsBegin((PetscObject)prob);
319: for (b = prob->boundary; b; b = b->next) {
320: char optname[1024];
321: PetscInt ids[1024], len = 1024;
322: PetscBool flg;
324: PetscCall(PetscSNPrintf(optname, sizeof(optname), "-bc_%s", b->name));
325: PetscCall(PetscMemzero(ids, sizeof(ids)));
326: PetscCall(PetscOptionsIntArray(optname, "List of boundary IDs", "", ids, &len, &flg));
327: if (flg) {
328: b->Nv = len;
329: PetscCall(PetscFree(b->values));
330: PetscCall(PetscMalloc1(len, &b->values));
331: PetscCall(PetscArraycpy(b->values, ids, len));
332: PetscCall(PetscWeakFormRewriteKeys(b->wf, b->label, len, b->values));
333: }
334: len = 1024;
335: PetscCall(PetscSNPrintf(optname, sizeof(optname), "-bc_%s_comp", b->name));
336: PetscCall(PetscMemzero(ids, sizeof(ids)));
337: PetscCall(PetscOptionsIntArray(optname, "List of boundary field components", "", ids, &len, &flg));
338: if (flg) {
339: b->Nc = len;
340: PetscCall(PetscFree(b->comps));
341: PetscCall(PetscMalloc1(len, &b->comps));
342: PetscCall(PetscArraycpy(b->comps, ids, len));
343: }
344: }
345: PetscCall(PetscOptionsFList("-petscds_type", "Discrete System", "PetscDSSetType", PetscDSList, defaultType, name, 256, &flg));
346: if (flg) {
347: PetscCall(PetscDSSetType(prob, name));
348: } else if (!((PetscObject)prob)->type_name) {
349: PetscCall(PetscDSSetType(prob, defaultType));
350: }
351: PetscCall(PetscOptionsBool("-petscds_jac_pre", "Discrete System", "PetscDSUseJacobianPreconditioner", prob->useJacPre, &prob->useJacPre, &flg));
352: PetscCall(PetscOptionsBool("-petscds_force_quad", "Discrete System", "PetscDSSetForceQuad", prob->forceQuad, &prob->forceQuad, &flg));
353: PetscTryTypeMethod(prob, setfromoptions);
354: /* process any options handlers added with PetscObjectAddOptionsHandler() */
355: PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)prob, PetscOptionsObject));
356: PetscOptionsEnd();
357: if (prob->Nf) PetscCall(PetscDSViewFromOptions(prob, NULL, "-petscds_view"));
358: PetscFunctionReturn(PETSC_SUCCESS);
359: }
361: /*@C
362: PetscDSSetUp - Construct data structures for the `PetscDS`
364: Collective
366: Input Parameter:
367: . prob - the `PetscDS` object to setup
369: Level: developer
371: .seealso: `PetscDS`, `PetscDSView()`, `PetscDSDestroy()`
372: @*/
373: PetscErrorCode PetscDSSetUp(PetscDS prob)
374: {
375: const PetscInt Nf = prob->Nf;
376: PetscBool hasH = PETSC_FALSE;
377: PetscInt maxOrder[4] = {-1, -1, -1, -1};
378: PetscInt dim, dimEmbed, NbMax = 0, NcMax = 0, NqMax = 0, NsMax = 1, f;
380: PetscFunctionBegin;
382: if (prob->setup) PetscFunctionReturn(PETSC_SUCCESS);
383: /* Calculate sizes */
384: PetscCall(PetscDSGetSpatialDimension(prob, &dim));
385: PetscCall(PetscDSGetCoordinateDimension(prob, &dimEmbed));
386: prob->totDim = prob->totComp = 0;
387: PetscCall(PetscMalloc2(Nf, &prob->Nc, Nf, &prob->Nb));
388: PetscCall(PetscCalloc2(Nf + 1, &prob->off, Nf + 1, &prob->offDer));
389: 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]));
390: PetscCall(PetscMalloc2(Nf, &prob->T, Nf, &prob->Tf));
391: if (prob->forceQuad) {
392: // Note: This assumes we have one kind of cell at each dimension.
393: // We can fix this by having quadrature hold the celltype
394: PetscQuadrature maxQuad[4] = {NULL, NULL, NULL, NULL};
396: for (f = 0; f < Nf; ++f) {
397: PetscObject obj;
398: PetscClassId id;
399: PetscQuadrature q = NULL, fq = NULL;
400: PetscInt dim = -1, order = -1, forder = -1;
402: PetscCall(PetscDSGetDiscretization(prob, f, &obj));
403: if (!obj) continue;
404: PetscCall(PetscObjectGetClassId(obj, &id));
405: if (id == PETSCFE_CLASSID) {
406: PetscFE fe = (PetscFE)obj;
408: PetscCall(PetscFEGetQuadrature(fe, &q));
409: PetscCall(PetscFEGetFaceQuadrature(fe, &fq));
410: } else if (id == PETSCFV_CLASSID) {
411: PetscFV fv = (PetscFV)obj;
413: PetscCall(PetscFVGetQuadrature(fv, &q));
414: }
415: if (q) {
416: PetscCall(PetscQuadratureGetData(q, &dim, NULL, NULL, NULL, NULL));
417: PetscCall(PetscQuadratureGetOrder(q, &order));
418: if (order > maxOrder[dim]) {
419: maxOrder[dim] = order;
420: maxQuad[dim] = q;
421: }
422: }
423: if (fq) {
424: PetscCall(PetscQuadratureGetData(fq, &dim, NULL, NULL, NULL, NULL));
425: PetscCall(PetscQuadratureGetOrder(fq, &forder));
426: if (forder > maxOrder[dim]) {
427: maxOrder[dim] = forder;
428: maxQuad[dim] = fq;
429: }
430: }
431: }
432: for (f = 0; f < Nf; ++f) {
433: PetscObject obj;
434: PetscClassId id;
435: PetscQuadrature q;
436: PetscInt dim;
438: PetscCall(PetscDSGetDiscretization(prob, f, &obj));
439: if (!obj) continue;
440: PetscCall(PetscObjectGetClassId(obj, &id));
441: if (id == PETSCFE_CLASSID) {
442: PetscFE fe = (PetscFE)obj;
444: PetscCall(PetscFEGetQuadrature(fe, &q));
445: PetscCall(PetscQuadratureGetData(q, &dim, NULL, NULL, NULL, NULL));
446: PetscCall(PetscFESetQuadrature(fe, maxQuad[dim]));
447: PetscCall(PetscFESetFaceQuadrature(fe, maxQuad[dim - 1]));
448: } else if (id == PETSCFV_CLASSID) {
449: PetscFV fv = (PetscFV)obj;
451: PetscCall(PetscFVGetQuadrature(fv, &q));
452: PetscCall(PetscQuadratureGetData(q, &dim, NULL, NULL, NULL, NULL));
453: PetscCall(PetscFVSetQuadrature(fv, maxQuad[dim]));
454: }
455: }
456: }
457: for (f = 0; f < Nf; ++f) {
458: PetscObject obj;
459: PetscClassId id;
460: PetscQuadrature q = NULL;
461: PetscInt Nq = 0, Nb, Nc;
463: PetscCall(PetscDSGetDiscretization(prob, f, &obj));
464: if (prob->jetDegree[f] > 1) hasH = PETSC_TRUE;
465: if (!obj) {
466: /* Empty mesh */
467: Nb = Nc = 0;
468: prob->T[f] = prob->Tf[f] = NULL;
469: } else {
470: PetscCall(PetscObjectGetClassId(obj, &id));
471: if (id == PETSCFE_CLASSID) {
472: PetscFE fe = (PetscFE)obj;
474: PetscCall(PetscFEGetQuadrature(fe, &q));
475: {
476: PetscQuadrature fq;
477: PetscInt dim, order;
479: PetscCall(PetscQuadratureGetData(q, &dim, NULL, NULL, NULL, NULL));
480: PetscCall(PetscQuadratureGetOrder(q, &order));
481: if (maxOrder[dim] < 0) maxOrder[dim] = order;
482: PetscCheck(order == maxOrder[dim], PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Field %" PetscInt_FMT " cell quadrature order %" PetscInt_FMT " != %" PetscInt_FMT " DS cell quadrature order", f, order, maxOrder[dim]);
483: PetscCall(PetscFEGetFaceQuadrature(fe, &fq));
484: if (fq) {
485: PetscCall(PetscQuadratureGetData(fq, &dim, NULL, NULL, NULL, NULL));
486: PetscCall(PetscQuadratureGetOrder(fq, &order));
487: if (maxOrder[dim] < 0) maxOrder[dim] = order;
488: PetscCheck(order == maxOrder[dim], PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Field %" PetscInt_FMT " face quadrature order %" PetscInt_FMT " != %" PetscInt_FMT " DS face quadrature order", f, order, maxOrder[dim]);
489: }
490: }
491: PetscCall(PetscFEGetDimension(fe, &Nb));
492: PetscCall(PetscFEGetNumComponents(fe, &Nc));
493: PetscCall(PetscFEGetCellTabulation(fe, prob->jetDegree[f], &prob->T[f]));
494: PetscCall(PetscFEGetFaceTabulation(fe, prob->jetDegree[f], &prob->Tf[f]));
495: } else if (id == PETSCFV_CLASSID) {
496: PetscFV fv = (PetscFV)obj;
498: PetscCall(PetscFVGetQuadrature(fv, &q));
499: PetscCall(PetscFVGetNumComponents(fv, &Nc));
500: Nb = Nc;
501: PetscCall(PetscFVGetCellTabulation(fv, &prob->T[f]));
502: /* TODO: should PetscFV also have face tabulation? Otherwise there will be a null pointer in prob->basisFace */
503: } else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, f);
504: }
505: prob->Nc[f] = Nc;
506: prob->Nb[f] = Nb;
507: prob->off[f + 1] = Nc + prob->off[f];
508: prob->offDer[f + 1] = Nc * dim + prob->offDer[f];
509: prob->offCohesive[0][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) + prob->offCohesive[0][f];
510: prob->offDerCohesive[0][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) * dimEmbed + prob->offDerCohesive[0][f];
511: prob->offCohesive[1][f] = (prob->cohesive[f] ? 0 : Nc) + prob->offCohesive[0][f];
512: prob->offDerCohesive[1][f] = (prob->cohesive[f] ? 0 : Nc) * dimEmbed + prob->offDerCohesive[0][f];
513: prob->offCohesive[2][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) + prob->offCohesive[2][f];
514: prob->offDerCohesive[2][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) * dimEmbed + prob->offDerCohesive[2][f];
515: if (q) PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Nq, NULL, NULL));
516: NqMax = PetscMax(NqMax, Nq);
517: NbMax = PetscMax(NbMax, Nb);
518: NcMax = PetscMax(NcMax, Nc);
519: prob->totDim += Nb;
520: prob->totComp += Nc;
521: /* There are two faces for all fields on a cohesive cell, except for cohesive fields */
522: if (prob->isCohesive && !prob->cohesive[f]) prob->totDim += Nb;
523: }
524: prob->offCohesive[1][Nf] = prob->offCohesive[0][Nf];
525: prob->offDerCohesive[1][Nf] = prob->offDerCohesive[0][Nf];
526: /* Allocate works space */
527: NsMax = 2; /* A non-cohesive discretizations can be used on a cohesive cell, so we need this extra workspace for all DS */
528: 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));
529: PetscCall(PetscMalloc5(dimEmbed, &prob->x, NbMax * NcMax, &prob->basisReal, NbMax * NcMax * dimEmbed, &prob->basisDerReal, NbMax * NcMax, &prob->testReal, NbMax * NcMax * dimEmbed, &prob->testDerReal));
530: 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,
531: &prob->g2, NsMax * NsMax * NqMax * NcMax * NcMax * dimEmbed * dimEmbed, &prob->g3));
532: PetscTryTypeMethod(prob, setup);
533: prob->setup = PETSC_TRUE;
534: PetscFunctionReturn(PETSC_SUCCESS);
535: }
537: static PetscErrorCode PetscDSDestroyStructs_Static(PetscDS prob)
538: {
539: PetscFunctionBegin;
540: PetscCall(PetscFree2(prob->Nc, prob->Nb));
541: PetscCall(PetscFree2(prob->off, prob->offDer));
542: PetscCall(PetscFree6(prob->offCohesive[0], prob->offCohesive[1], prob->offCohesive[2], prob->offDerCohesive[0], prob->offDerCohesive[1], prob->offDerCohesive[2]));
543: PetscCall(PetscFree2(prob->T, prob->Tf));
544: PetscCall(PetscFree3(prob->u, prob->u_t, prob->u_x));
545: PetscCall(PetscFree5(prob->x, prob->basisReal, prob->basisDerReal, prob->testReal, prob->testDerReal));
546: PetscCall(PetscFree6(prob->f0, prob->f1, prob->g0, prob->g1, prob->g2, prob->g3));
547: PetscFunctionReturn(PETSC_SUCCESS);
548: }
550: static PetscErrorCode PetscDSEnlarge_Static(PetscDS prob, PetscInt NfNew)
551: {
552: PetscObject *tmpd;
553: PetscBool *tmpi;
554: PetscInt *tmpk;
555: PetscBool *tmpc;
556: PetscPointFunc *tmpup;
557: PetscSimplePointFunc *tmpexactSol, *tmpexactSol_t;
558: void **tmpexactCtx, **tmpexactCtx_t;
559: void **tmpctx;
560: PetscInt Nf = prob->Nf, f;
562: PetscFunctionBegin;
563: if (Nf >= NfNew) PetscFunctionReturn(PETSC_SUCCESS);
564: prob->setup = PETSC_FALSE;
565: PetscCall(PetscDSDestroyStructs_Static(prob));
566: PetscCall(PetscMalloc4(NfNew, &tmpd, NfNew, &tmpi, NfNew, &tmpc, NfNew, &tmpk));
567: for (f = 0; f < Nf; ++f) {
568: tmpd[f] = prob->disc[f];
569: tmpi[f] = prob->implicit[f];
570: tmpc[f] = prob->cohesive[f];
571: tmpk[f] = prob->jetDegree[f];
572: }
573: for (f = Nf; f < NfNew; ++f) {
574: tmpd[f] = NULL;
575: tmpi[f] = PETSC_TRUE, tmpc[f] = PETSC_FALSE;
576: tmpk[f] = 1;
577: }
578: PetscCall(PetscFree4(prob->disc, prob->implicit, prob->cohesive, prob->jetDegree));
579: PetscCall(PetscWeakFormSetNumFields(prob->wf, NfNew));
580: prob->Nf = NfNew;
581: prob->disc = tmpd;
582: prob->implicit = tmpi;
583: prob->cohesive = tmpc;
584: prob->jetDegree = tmpk;
585: PetscCall(PetscCalloc2(NfNew, &tmpup, NfNew, &tmpctx));
586: for (f = 0; f < Nf; ++f) tmpup[f] = prob->update[f];
587: for (f = 0; f < Nf; ++f) tmpctx[f] = prob->ctx[f];
588: for (f = Nf; f < NfNew; ++f) tmpup[f] = NULL;
589: for (f = Nf; f < NfNew; ++f) tmpctx[f] = NULL;
590: PetscCall(PetscFree2(prob->update, prob->ctx));
591: prob->update = tmpup;
592: prob->ctx = tmpctx;
593: PetscCall(PetscCalloc4(NfNew, &tmpexactSol, NfNew, &tmpexactCtx, NfNew, &tmpexactSol_t, NfNew, &tmpexactCtx_t));
594: for (f = 0; f < Nf; ++f) tmpexactSol[f] = prob->exactSol[f];
595: for (f = 0; f < Nf; ++f) tmpexactCtx[f] = prob->exactCtx[f];
596: for (f = 0; f < Nf; ++f) tmpexactSol_t[f] = prob->exactSol_t[f];
597: for (f = 0; f < Nf; ++f) tmpexactCtx_t[f] = prob->exactCtx_t[f];
598: for (f = Nf; f < NfNew; ++f) tmpexactSol[f] = NULL;
599: for (f = Nf; f < NfNew; ++f) tmpexactCtx[f] = NULL;
600: for (f = Nf; f < NfNew; ++f) tmpexactSol_t[f] = NULL;
601: for (f = Nf; f < NfNew; ++f) tmpexactCtx_t[f] = NULL;
602: PetscCall(PetscFree4(prob->exactSol, prob->exactCtx, prob->exactSol_t, prob->exactCtx_t));
603: prob->exactSol = tmpexactSol;
604: prob->exactCtx = tmpexactCtx;
605: prob->exactSol_t = tmpexactSol_t;
606: prob->exactCtx_t = tmpexactCtx_t;
607: PetscFunctionReturn(PETSC_SUCCESS);
608: }
610: /*@
611: PetscDSDestroy - Destroys a `PetscDS` object
613: Collective
615: Input Parameter:
616: . prob - the `PetscDS` object to destroy
618: Level: developer
620: .seealso: `PetscDSView()`
621: @*/
622: PetscErrorCode PetscDSDestroy(PetscDS *ds)
623: {
624: PetscInt f;
626: PetscFunctionBegin;
627: if (!*ds) PetscFunctionReturn(PETSC_SUCCESS);
630: if (--((PetscObject)(*ds))->refct > 0) {
631: *ds = NULL;
632: PetscFunctionReturn(PETSC_SUCCESS);
633: }
634: ((PetscObject)(*ds))->refct = 0;
635: if ((*ds)->subprobs) {
636: PetscInt dim, d;
638: PetscCall(PetscDSGetSpatialDimension(*ds, &dim));
639: for (d = 0; d < dim; ++d) PetscCall(PetscDSDestroy(&(*ds)->subprobs[d]));
640: }
641: PetscCall(PetscFree((*ds)->subprobs));
642: PetscCall(PetscDSDestroyStructs_Static(*ds));
643: for (f = 0; f < (*ds)->Nf; ++f) PetscCall(PetscObjectDereference((*ds)->disc[f]));
644: PetscCall(PetscFree4((*ds)->disc, (*ds)->implicit, (*ds)->cohesive, (*ds)->jetDegree));
645: PetscCall(PetscWeakFormDestroy(&(*ds)->wf));
646: PetscCall(PetscFree2((*ds)->update, (*ds)->ctx));
647: PetscCall(PetscFree4((*ds)->exactSol, (*ds)->exactCtx, (*ds)->exactSol_t, (*ds)->exactCtx_t));
648: PetscTryTypeMethod((*ds), destroy);
649: PetscCall(PetscDSDestroyBoundary(*ds));
650: PetscCall(PetscFree((*ds)->constants));
651: for (PetscInt c = 0; c < DM_NUM_POLYTOPES; ++c) {
652: const PetscInt Na = DMPolytopeTypeGetNumArrangments((DMPolytopeType)c);
653: if ((*ds)->quadPerm[c])
654: for (PetscInt o = 0; o < Na; ++o) PetscCall(ISDestroy(&(*ds)->quadPerm[c][o]));
655: PetscCall(PetscFree((*ds)->quadPerm[c]));
656: (*ds)->quadPerm[c] = NULL;
657: }
658: PetscCall(PetscHeaderDestroy(ds));
659: PetscFunctionReturn(PETSC_SUCCESS);
660: }
662: /*@
663: PetscDSCreate - Creates an empty `PetscDS` object. The type can then be set with `PetscDSSetType()`.
665: Collective
667: Input Parameter:
668: . comm - The communicator for the `PetscDS` object
670: Output Parameter:
671: . ds - The `PetscDS` object
673: Level: beginner
675: .seealso: `PetscDS`, `PetscDSSetType()`, `PETSCDSBASIC`, `PetscDSType`
676: @*/
677: PetscErrorCode PetscDSCreate(MPI_Comm comm, PetscDS *ds)
678: {
679: PetscDS p;
681: PetscFunctionBegin;
683: *ds = NULL;
684: PetscCall(PetscDSInitializePackage());
686: PetscCall(PetscHeaderCreate(p, PETSCDS_CLASSID, "PetscDS", "Discrete System", "PetscDS", comm, PetscDSDestroy, PetscDSView));
688: p->Nf = 0;
689: p->setup = PETSC_FALSE;
690: p->numConstants = 0;
691: p->constants = NULL;
692: p->dimEmbed = -1;
693: p->useJacPre = PETSC_TRUE;
694: p->forceQuad = PETSC_TRUE;
695: PetscCall(PetscWeakFormCreate(comm, &p->wf));
696: PetscCall(PetscArrayzero(p->quadPerm, DM_NUM_POLYTOPES));
698: *ds = p;
699: PetscFunctionReturn(PETSC_SUCCESS);
700: }
702: /*@
703: PetscDSGetNumFields - Returns the number of fields in the `PetscDS`
705: Not Collective
707: Input Parameter:
708: . prob - The `PetscDS` object
710: Output Parameter:
711: . Nf - The number of fields
713: Level: beginner
715: .seealso: `PetscDS`, `PetscDSGetSpatialDimension()`, `PetscDSCreate()`
716: @*/
717: PetscErrorCode PetscDSGetNumFields(PetscDS prob, PetscInt *Nf)
718: {
719: PetscFunctionBegin;
722: *Nf = prob->Nf;
723: PetscFunctionReturn(PETSC_SUCCESS);
724: }
726: /*@
727: PetscDSGetSpatialDimension - Returns the spatial dimension of the `PetscDS`, meaning the topological dimension of the discretizations
729: Not Collective
731: Input Parameter:
732: . prob - The `PetscDS` object
734: Output Parameter:
735: . dim - The spatial dimension
737: Level: beginner
739: .seealso: `PetscDS`, `PetscDSGetCoordinateDimension()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
740: @*/
741: PetscErrorCode PetscDSGetSpatialDimension(PetscDS prob, PetscInt *dim)
742: {
743: PetscFunctionBegin;
746: *dim = 0;
747: if (prob->Nf) {
748: PetscObject obj;
749: PetscClassId id;
751: PetscCall(PetscDSGetDiscretization(prob, 0, &obj));
752: if (obj) {
753: PetscCall(PetscObjectGetClassId(obj, &id));
754: if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetSpatialDimension((PetscFE)obj, dim));
755: else if (id == PETSCFV_CLASSID) PetscCall(PetscFVGetSpatialDimension((PetscFV)obj, dim));
756: else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
757: }
758: }
759: PetscFunctionReturn(PETSC_SUCCESS);
760: }
762: /*@
763: PetscDSGetCoordinateDimension - Returns the coordinate dimension of the `PetscDS`, meaning the dimension of the space into which the discretiaztions are embedded
765: Not Collective
767: Input Parameter:
768: . prob - The `PetscDS` object
770: Output Parameter:
771: . dimEmbed - The coordinate dimension
773: Level: beginner
775: .seealso: `PetscDS`, `PetscDSSetCoordinateDimension()`, `PetscDSGetSpatialDimension()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
776: @*/
777: PetscErrorCode PetscDSGetCoordinateDimension(PetscDS prob, PetscInt *dimEmbed)
778: {
779: PetscFunctionBegin;
782: PetscCheck(prob->dimEmbed >= 0, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONGSTATE, "No coordinate dimension set for this DS");
783: *dimEmbed = prob->dimEmbed;
784: PetscFunctionReturn(PETSC_SUCCESS);
785: }
787: /*@
788: PetscDSSetCoordinateDimension - Set the coordinate dimension of the `PetscDS`, meaning the dimension of the space into which the discretiaztions are embedded
790: Logically Collective
792: Input Parameters:
793: + prob - The `PetscDS` object
794: - dimEmbed - The coordinate dimension
796: Level: beginner
798: .seealso: `PetscDS`, `PetscDSGetCoordinateDimension()`, `PetscDSGetSpatialDimension()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
799: @*/
800: PetscErrorCode PetscDSSetCoordinateDimension(PetscDS prob, PetscInt dimEmbed)
801: {
802: PetscFunctionBegin;
804: PetscCheck(dimEmbed >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate dimension must be non-negative, not %" PetscInt_FMT, dimEmbed);
805: prob->dimEmbed = dimEmbed;
806: PetscFunctionReturn(PETSC_SUCCESS);
807: }
809: /*@
810: PetscDSGetForceQuad - Returns the flag to force matching quadratures among the field discretizations
812: Not collective
814: Input Parameter:
815: . prob - The `PetscDS` object
817: Output Parameter:
818: . forceQuad - The flag
820: Level: intermediate
822: .seealso: `PetscDS`, `PetscDSSetForceQuad()`, `PetscDSGetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
823: @*/
824: PetscErrorCode PetscDSGetForceQuad(PetscDS ds, PetscBool *forceQuad)
825: {
826: PetscFunctionBegin;
829: *forceQuad = ds->forceQuad;
830: PetscFunctionReturn(PETSC_SUCCESS);
831: }
833: /*@
834: PetscDSSetForceQuad - Set the flag to force matching quadratures among the field discretizations
836: Logically collective on ds
838: Input Parameters:
839: + ds - The `PetscDS` object
840: - forceQuad - The flag
842: Level: intermediate
844: .seealso: `PetscDS`, `PetscDSGetForceQuad()`, `PetscDSGetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
845: @*/
846: PetscErrorCode PetscDSSetForceQuad(PetscDS ds, PetscBool forceQuad)
847: {
848: PetscFunctionBegin;
850: ds->forceQuad = forceQuad;
851: PetscFunctionReturn(PETSC_SUCCESS);
852: }
854: /*@
855: PetscDSIsCohesive - Returns the flag indicating that this `PetscDS` is for a cohesive cell
857: Not Collective
859: Input Parameter:
860: . ds - The `PetscDS` object
862: Output Parameter:
863: . isCohesive - The flag
865: Level: developer
867: .seealso: `PetscDS`, `PetscDSGetNumCohesive()`, `PetscDSGetCohesive()`, `PetscDSSetCohesive()`, `PetscDSCreate()`
868: @*/
869: PetscErrorCode PetscDSIsCohesive(PetscDS ds, PetscBool *isCohesive)
870: {
871: PetscFunctionBegin;
874: *isCohesive = ds->isCohesive;
875: PetscFunctionReturn(PETSC_SUCCESS);
876: }
878: /*@
879: PetscDSGetNumCohesive - Returns the numer of cohesive fields, meaning those defined on the interior of a cohesive cell
881: Not Collective
883: Input Parameter:
884: . ds - The `PetscDS` object
886: Output Parameter:
887: . numCohesive - The number of cohesive fields
889: Level: developer
891: .seealso: `PetscDS`, `PetscDSSetCohesive()`, `PetscDSCreate()`
892: @*/
893: PetscErrorCode PetscDSGetNumCohesive(PetscDS ds, PetscInt *numCohesive)
894: {
895: PetscInt f;
897: PetscFunctionBegin;
900: *numCohesive = 0;
901: for (f = 0; f < ds->Nf; ++f) *numCohesive += ds->cohesive[f] ? 1 : 0;
902: PetscFunctionReturn(PETSC_SUCCESS);
903: }
905: /*@
906: PetscDSGetCohesive - Returns the flag indicating that a field is cohesive, meaning it is defined on the interior of a cohesive cell
908: Not Collective
910: Input Parameters:
911: + ds - The `PetscDS` object
912: - f - The field index
914: Output Parameter:
915: . isCohesive - The flag
917: Level: developer
919: .seealso: `PetscDS`, `PetscDSSetCohesive()`, `PetscDSIsCohesive()`, `PetscDSCreate()`
920: @*/
921: PetscErrorCode PetscDSGetCohesive(PetscDS ds, PetscInt f, PetscBool *isCohesive)
922: {
923: PetscFunctionBegin;
926: 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);
927: *isCohesive = ds->cohesive[f];
928: PetscFunctionReturn(PETSC_SUCCESS);
929: }
931: /*@
932: PetscDSSetCohesive - Set the flag indicating that a field is cohesive, meaning it is defined on the interior of a cohesive cell
934: Not Collective
936: Input Parameters:
937: + ds - The `PetscDS` object
938: . f - The field index
939: - isCohesive - The flag for a cohesive field
941: Level: developer
943: .seealso: `PetscDS`, `PetscDSGetCohesive()`, `PetscDSIsCohesive()`, `PetscDSCreate()`
944: @*/
945: PetscErrorCode PetscDSSetCohesive(PetscDS ds, PetscInt f, PetscBool isCohesive)
946: {
947: PetscInt i;
949: PetscFunctionBegin;
951: 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);
952: ds->cohesive[f] = isCohesive;
953: ds->isCohesive = PETSC_FALSE;
954: for (i = 0; i < ds->Nf; ++i) ds->isCohesive = ds->isCohesive || ds->cohesive[f] ? PETSC_TRUE : PETSC_FALSE;
955: PetscFunctionReturn(PETSC_SUCCESS);
956: }
958: /*@
959: PetscDSGetTotalDimension - Returns the total size of the approximation space for this system
961: Not Collective
963: Input Parameter:
964: . prob - The `PetscDS` object
966: Output Parameter:
967: . dim - The total problem dimension
969: Level: beginner
971: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
972: @*/
973: PetscErrorCode PetscDSGetTotalDimension(PetscDS prob, PetscInt *dim)
974: {
975: PetscFunctionBegin;
977: PetscCall(PetscDSSetUp(prob));
979: *dim = prob->totDim;
980: PetscFunctionReturn(PETSC_SUCCESS);
981: }
983: /*@
984: PetscDSGetTotalComponents - Returns the total number of components in this system
986: Not Collective
988: Input Parameter:
989: . prob - The `PetscDS` object
991: Output Parameter:
992: . dim - The total number of components
994: Level: beginner
996: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
997: @*/
998: PetscErrorCode PetscDSGetTotalComponents(PetscDS prob, PetscInt *Nc)
999: {
1000: PetscFunctionBegin;
1002: PetscCall(PetscDSSetUp(prob));
1004: *Nc = prob->totComp;
1005: PetscFunctionReturn(PETSC_SUCCESS);
1006: }
1008: /*@
1009: PetscDSGetDiscretization - Returns the discretization object for the given field
1011: Not Collective
1013: Input Parameters:
1014: + prob - The `PetscDS` object
1015: - f - The field number
1017: Output Parameter:
1018: . disc - The discretization object
1020: Level: beginner
1022: .seealso: `PetscDS`, `PetscFE`, `PetscFV`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1023: @*/
1024: PetscErrorCode PetscDSGetDiscretization(PetscDS prob, PetscInt f, PetscObject *disc)
1025: {
1026: PetscFunctionBeginHot;
1029: 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);
1030: *disc = prob->disc[f];
1031: PetscFunctionReturn(PETSC_SUCCESS);
1032: }
1034: /*@
1035: PetscDSSetDiscretization - Sets the discretization object for the given field
1037: Not Collective
1039: Input Parameters:
1040: + prob - The `PetscDS` object
1041: . f - The field number
1042: - disc - The discretization object
1044: Level: beginner
1046: .seealso: `PetscDS`, `PetscFE`, `PetscFV`, `PetscDSGetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1047: @*/
1048: PetscErrorCode PetscDSSetDiscretization(PetscDS prob, PetscInt f, PetscObject disc)
1049: {
1050: PetscFunctionBegin;
1053: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1054: PetscCall(PetscDSEnlarge_Static(prob, f + 1));
1055: PetscCall(PetscObjectDereference(prob->disc[f]));
1056: prob->disc[f] = disc;
1057: PetscCall(PetscObjectReference(disc));
1058: if (disc) {
1059: PetscClassId id;
1061: PetscCall(PetscObjectGetClassId(disc, &id));
1062: if (id == PETSCFE_CLASSID) {
1063: PetscCall(PetscDSSetImplicit(prob, f, PETSC_TRUE));
1064: } else if (id == PETSCFV_CLASSID) {
1065: PetscCall(PetscDSSetImplicit(prob, f, PETSC_FALSE));
1066: }
1067: PetscCall(PetscDSSetJetDegree(prob, f, 1));
1068: }
1069: PetscFunctionReturn(PETSC_SUCCESS);
1070: }
1072: /*@
1073: PetscDSGetWeakForm - Returns the weak form object
1075: Not Collective
1077: Input Parameter:
1078: . ds - The `PetscDS` object
1080: Output Parameter:
1081: . wf - The weak form object
1083: Level: beginner
1085: .seealso: `PetscWeakForm`, `PetscDSSetWeakForm()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1086: @*/
1087: PetscErrorCode PetscDSGetWeakForm(PetscDS ds, PetscWeakForm *wf)
1088: {
1089: PetscFunctionBegin;
1092: *wf = ds->wf;
1093: PetscFunctionReturn(PETSC_SUCCESS);
1094: }
1096: /*@
1097: PetscDSSetWeakForm - Sets the weak form object
1099: Not Collective
1101: Input Parameters:
1102: + ds - The `PetscDS` object
1103: - wf - The weak form object
1105: Level: beginner
1107: .seealso: `PetscWeakForm`, `PetscDSGetWeakForm()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1108: @*/
1109: PetscErrorCode PetscDSSetWeakForm(PetscDS ds, PetscWeakForm wf)
1110: {
1111: PetscFunctionBegin;
1114: PetscCall(PetscObjectDereference((PetscObject)ds->wf));
1115: ds->wf = wf;
1116: PetscCall(PetscObjectReference((PetscObject)wf));
1117: PetscCall(PetscWeakFormSetNumFields(wf, ds->Nf));
1118: PetscFunctionReturn(PETSC_SUCCESS);
1119: }
1121: /*@
1122: PetscDSAddDiscretization - Adds a discretization object
1124: Not Collective
1126: Input Parameters:
1127: + prob - The `PetscDS` object
1128: - disc - The boundary discretization object
1130: Level: beginner
1132: .seealso: `PetscWeakForm`, `PetscDSGetDiscretization()`, `PetscDSSetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1133: @*/
1134: PetscErrorCode PetscDSAddDiscretization(PetscDS prob, PetscObject disc)
1135: {
1136: PetscFunctionBegin;
1137: PetscCall(PetscDSSetDiscretization(prob, prob->Nf, disc));
1138: PetscFunctionReturn(PETSC_SUCCESS);
1139: }
1141: /*@
1142: PetscDSGetQuadrature - Returns the quadrature, which must agree for all fields in the `PetscDS`
1144: Not Collective
1146: Input Parameter:
1147: . prob - The `PetscDS` object
1149: Output Parameter:
1150: . q - The quadrature object
1152: Level: intermediate
1154: .seealso: `PetscDS`, `PetscQuadrature`, `PetscDSSetImplicit()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1155: @*/
1156: PetscErrorCode PetscDSGetQuadrature(PetscDS prob, PetscQuadrature *q)
1157: {
1158: PetscObject obj;
1159: PetscClassId id;
1161: PetscFunctionBegin;
1162: *q = NULL;
1163: if (!prob->Nf) PetscFunctionReturn(PETSC_SUCCESS);
1164: PetscCall(PetscDSGetDiscretization(prob, 0, &obj));
1165: PetscCall(PetscObjectGetClassId(obj, &id));
1166: if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetQuadrature((PetscFE)obj, q));
1167: else if (id == PETSCFV_CLASSID) PetscCall(PetscFVGetQuadrature((PetscFV)obj, q));
1168: else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
1169: PetscFunctionReturn(PETSC_SUCCESS);
1170: }
1172: /*@
1173: PetscDSGetImplicit - Returns the flag for implicit solve for this field. This is just a guide for `TSIMEX`
1175: Not Collective
1177: Input Parameters:
1178: + prob - The `PetscDS` object
1179: - f - The field number
1181: Output Parameter:
1182: . implicit - The flag indicating what kind of solve to use for this field
1184: Level: developer
1186: .seealso: `TSIMEX`, `PetscDS`, `PetscDSSetImplicit()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1187: @*/
1188: PetscErrorCode PetscDSGetImplicit(PetscDS prob, PetscInt f, PetscBool *implicit)
1189: {
1190: PetscFunctionBegin;
1193: 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);
1194: *implicit = prob->implicit[f];
1195: PetscFunctionReturn(PETSC_SUCCESS);
1196: }
1198: /*@
1199: PetscDSSetImplicit - Set the flag for implicit solve for this field. This is just a guide for `TSIMEX`
1201: Not Collective
1203: Input Parameters:
1204: + prob - The `PetscDS` object
1205: . f - The field number
1206: - implicit - The flag indicating what kind of solve to use for this field
1208: Level: developer
1210: .seealso: `TSIMEX`, `PetscDSGetImplicit()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1211: @*/
1212: PetscErrorCode PetscDSSetImplicit(PetscDS prob, PetscInt f, PetscBool implicit)
1213: {
1214: PetscFunctionBegin;
1216: 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);
1217: prob->implicit[f] = implicit;
1218: PetscFunctionReturn(PETSC_SUCCESS);
1219: }
1221: /*@
1222: PetscDSGetJetDegree - Returns the highest derivative for this field equation, or the k-jet that the discretization needs to tabulate.
1224: Not Collective
1226: Input Parameters:
1227: + ds - The `PetscDS` object
1228: - f - The field number
1230: Output Parameter:
1231: . k - The highest derivative we need to tabulate
1233: Level: developer
1235: .seealso: `PetscDS`, `PetscDSSetJetDegree()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1236: @*/
1237: PetscErrorCode PetscDSGetJetDegree(PetscDS ds, PetscInt f, PetscInt *k)
1238: {
1239: PetscFunctionBegin;
1242: 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);
1243: *k = ds->jetDegree[f];
1244: PetscFunctionReturn(PETSC_SUCCESS);
1245: }
1247: /*@
1248: PetscDSSetJetDegree - Set the highest derivative for this field equation, or the k-jet that the discretization needs to tabulate.
1250: Not Collective
1252: Input Parameters:
1253: + ds - The `PetscDS` object
1254: . f - The field number
1255: - k - The highest derivative we need to tabulate
1257: Level: developer
1259: .seealso: ``PetscDS`, PetscDSGetJetDegree()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1260: @*/
1261: PetscErrorCode PetscDSSetJetDegree(PetscDS ds, PetscInt f, PetscInt k)
1262: {
1263: PetscFunctionBegin;
1265: 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);
1266: ds->jetDegree[f] = k;
1267: PetscFunctionReturn(PETSC_SUCCESS);
1268: }
1270: 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[]))
1271: {
1272: PetscPointFunc *tmp;
1273: PetscInt n;
1275: PetscFunctionBegin;
1278: 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);
1279: PetscCall(PetscWeakFormGetObjective(ds->wf, NULL, 0, f, 0, &n, &tmp));
1280: *obj = tmp ? tmp[0] : NULL;
1281: PetscFunctionReturn(PETSC_SUCCESS);
1282: }
1284: 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[]))
1285: {
1286: PetscFunctionBegin;
1289: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1290: PetscCall(PetscWeakFormSetIndexObjective(ds->wf, NULL, 0, f, 0, 0, obj));
1291: PetscFunctionReturn(PETSC_SUCCESS);
1292: }
1294: /*@C
1295: PetscDSGetResidual - Get the pointwise residual function for a given test field
1297: Not Collective
1299: Input Parameters:
1300: + ds - The `PetscDS`
1301: - f - The test field number
1303: Output Parameters:
1304: + f0 - integrand for the test function term
1305: - f1 - integrand for the test function gradient term
1307: Calling sequence of `f0` and `f1`:
1308: .vb
1309: void f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1310: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1311: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1312: PetscReal t, const PetscReal x[], PetscScalar f0[])
1313: .ve
1314: + dim - the spatial dimension
1315: . Nf - the number of fields
1316: . uOff - the offset into u[] and u_t[] for each field
1317: . uOff_x - the offset into u_x[] for each field
1318: . u - each field evaluated at the current point
1319: . u_t - the time derivative of each field evaluated at the current point
1320: . u_x - the gradient of each field evaluated at the current point
1321: . aOff - the offset into a[] and a_t[] for each auxiliary field
1322: . aOff_x - the offset into a_x[] for each auxiliary field
1323: . a - each auxiliary field evaluated at the current point
1324: . a_t - the time derivative of each auxiliary field evaluated at the current point
1325: . a_x - the gradient of auxiliary each field evaluated at the current point
1326: . t - current time
1327: . x - coordinates of the current point
1328: . numConstants - number of constant parameters
1329: . constants - constant parameters
1330: - f0 - output values at the current point
1332: Level: intermediate
1334: Note:
1335: 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)
1337: .seealso: `PetscDS`, `PetscDSSetResidual()`
1338: @*/
1339: 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[]))
1340: {
1341: PetscPointFunc *tmp0, *tmp1;
1342: PetscInt n0, n1;
1344: PetscFunctionBegin;
1346: 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);
1347: PetscCall(PetscWeakFormGetResidual(ds->wf, NULL, 0, f, 0, &n0, &tmp0, &n1, &tmp1));
1348: *f0 = tmp0 ? tmp0[0] : NULL;
1349: *f1 = tmp1 ? tmp1[0] : NULL;
1350: PetscFunctionReturn(PETSC_SUCCESS);
1351: }
1353: /*@C
1354: PetscDSSetResidual - Set the pointwise residual function for a given test field
1356: Not Collective
1358: Input Parameters:
1359: + ds - The `PetscDS`
1360: . f - The test field number
1361: . f0 - integrand for the test function term
1362: - f1 - integrand for the test function gradient term
1364: Calling sequence of `f0` and `f1`:
1365: .vb
1366: void f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1367: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1368: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1369: PetscReal t, const PetscReal x[], PetscScalar f0[])
1370: .ve
1371: + dim - the spatial dimension
1372: . Nf - the number of fields
1373: . uOff - the offset into u[] and u_t[] for each field
1374: . uOff_x - the offset into u_x[] for each field
1375: . u - each field evaluated at the current point
1376: . u_t - the time derivative of each field evaluated at the current point
1377: . u_x - the gradient of each field evaluated at the current point
1378: . aOff - the offset into a[] and a_t[] for each auxiliary field
1379: . aOff_x - the offset into a_x[] for each auxiliary field
1380: . a - each auxiliary field evaluated at the current point
1381: . a_t - the time derivative of each auxiliary field evaluated at the current point
1382: . a_x - the gradient of auxiliary each field evaluated at the current point
1383: . t - current time
1384: . x - coordinates of the current point
1385: . numConstants - number of constant parameters
1386: . constants - constant parameters
1387: - f0 - output values at the current point
1389: Level: intermediate
1391: Note:
1392: 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)
1394: .seealso: `PetscDS`, `PetscDSGetResidual()`
1395: @*/
1396: 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[]))
1397: {
1398: PetscFunctionBegin;
1402: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1403: PetscCall(PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1));
1404: PetscFunctionReturn(PETSC_SUCCESS);
1405: }
1407: /*@C
1408: PetscDSGetRHSResidual - Get the pointwise RHS residual function for explicit timestepping for a given test field
1410: Not Collective
1412: Input Parameters:
1413: + ds - The `PetscDS`
1414: - f - The test field number
1416: Output Parameters:
1417: + f0 - integrand for the test function term
1418: - f1 - integrand for the test function gradient term
1420: Calling sequence of `f0` and `f1`:
1421: .vb
1422: void f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1423: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1424: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1425: PetscReal t, const PetscReal x[], PetscScalar f0[])
1426: .ve
1427: + dim - the spatial dimension
1428: . Nf - the number of fields
1429: . uOff - the offset into u[] and u_t[] for each field
1430: . uOff_x - the offset into u_x[] for each field
1431: . u - each field evaluated at the current point
1432: . u_t - the time derivative of each field evaluated at the current point
1433: . u_x - the gradient of each field evaluated at the current point
1434: . aOff - the offset into a[] and a_t[] for each auxiliary field
1435: . aOff_x - the offset into a_x[] for each auxiliary field
1436: . a - each auxiliary field evaluated at the current point
1437: . a_t - the time derivative of each auxiliary field evaluated at the current point
1438: . a_x - the gradient of auxiliary each field evaluated at the current point
1439: . t - current time
1440: . x - coordinates of the current point
1441: . numConstants - number of constant parameters
1442: . constants - constant parameters
1443: - f0 - output values at the current point
1445: Level: intermediate
1447: Note:
1448: 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)
1450: .seealso: `PetscDS`, `PetscDSSetRHSResidual()`
1451: @*/
1452: 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[]))
1453: {
1454: PetscPointFunc *tmp0, *tmp1;
1455: PetscInt n0, n1;
1457: PetscFunctionBegin;
1459: 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);
1460: PetscCall(PetscWeakFormGetResidual(ds->wf, NULL, 0, f, 100, &n0, &tmp0, &n1, &tmp1));
1461: *f0 = tmp0 ? tmp0[0] : NULL;
1462: *f1 = tmp1 ? tmp1[0] : NULL;
1463: PetscFunctionReturn(PETSC_SUCCESS);
1464: }
1466: /*@C
1467: PetscDSSetRHSResidual - Set the pointwise residual function for explicit timestepping for a given test field
1469: Not Collective
1471: Input Parameters:
1472: + ds - The `PetscDS`
1473: . f - The test field number
1474: . f0 - integrand for the test function term
1475: - f1 - integrand for the test function gradient term
1477: Clling sequence for the callbacks f0 and f1:
1478: .vb
1479: f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1480: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1481: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1482: PetscReal t, const PetscReal x[], PetscScalar f0[])
1483: .ve
1484: + dim - the spatial dimension
1485: . Nf - the number of fields
1486: . uOff - the offset into u[] and u_t[] for each field
1487: . uOff_x - the offset into u_x[] for each field
1488: . u - each field evaluated at the current point
1489: . u_t - the time derivative of each field evaluated at the current point
1490: . u_x - the gradient of each field evaluated at the current point
1491: . aOff - the offset into a[] and a_t[] for each auxiliary field
1492: . aOff_x - the offset into a_x[] for each auxiliary field
1493: . a - each auxiliary field evaluated at the current point
1494: . a_t - the time derivative of each auxiliary field evaluated at the current point
1495: . a_x - the gradient of auxiliary each field evaluated at the current point
1496: . t - current time
1497: . x - coordinates of the current point
1498: . numConstants - number of constant parameters
1499: . constants - constant parameters
1500: - f0 - output values at the current point
1502: Level: intermediate
1504: Note:
1505: 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)
1507: .seealso: `PetscDS`, `PetscDSGetResidual()`
1508: @*/
1509: 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[]))
1510: {
1511: PetscFunctionBegin;
1515: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1516: PetscCall(PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 100, 0, f0, 0, f1));
1517: PetscFunctionReturn(PETSC_SUCCESS);
1518: }
1520: /*@C
1521: PetscDSHasJacobian - Checks that the Jacobian functions have been set
1523: Not Collective
1525: Input Parameter:
1526: . prob - The `PetscDS`
1528: Output Parameter:
1529: . hasJac - flag that pointwise function for the Jacobian has been set
1531: Level: intermediate
1533: .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`
1534: @*/
1535: PetscErrorCode PetscDSHasJacobian(PetscDS ds, PetscBool *hasJac)
1536: {
1537: PetscFunctionBegin;
1539: PetscCall(PetscWeakFormHasJacobian(ds->wf, hasJac));
1540: PetscFunctionReturn(PETSC_SUCCESS);
1541: }
1543: /*@C
1544: PetscDSGetJacobian - Get the pointwise Jacobian function for given test and basis field
1546: Not Collective
1548: Input Parameters:
1549: + ds - The `PetscDS`
1550: . f - The test field number
1551: - g - The field number
1553: Output Parameters:
1554: + g0 - integrand for the test and basis function term
1555: . g1 - integrand for the test function and basis function gradient term
1556: . g2 - integrand for the test function gradient and basis function term
1557: - g3 - integrand for the test function gradient and basis function gradient term
1559: Calling sequence of `g0`, `g1`, `g2` and `g3`:
1560: .vb
1561: void g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1562: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1563: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1564: PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])
1565: .ve
1566: + dim - the spatial dimension
1567: . Nf - the number of fields
1568: . uOff - the offset into u[] and u_t[] for each field
1569: . uOff_x - the offset into u_x[] for each field
1570: . u - each field evaluated at the current point
1571: . u_t - the time derivative of each field evaluated at the current point
1572: . u_x - the gradient of each field evaluated at the current point
1573: . aOff - the offset into a[] and a_t[] for each auxiliary field
1574: . aOff_x - the offset into a_x[] for each auxiliary field
1575: . a - each auxiliary field evaluated at the current point
1576: . a_t - the time derivative of each auxiliary field evaluated at the current point
1577: . a_x - the gradient of auxiliary each field evaluated at the current point
1578: . t - current time
1579: . u_tShift - the multiplier a for dF/dU_t
1580: . x - coordinates of the current point
1581: . numConstants - number of constant parameters
1582: . constants - constant parameters
1583: - g0 - output values at the current point
1585: Level: intermediate
1587: Note:
1588: We are using a first order FEM model for the weak form:
1589: \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
1591: .seealso: `PetscDS`, `PetscDSSetJacobian()`
1592: @*/
1593: 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[]))
1594: {
1595: PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
1596: PetscInt n0, n1, n2, n3;
1598: PetscFunctionBegin;
1600: 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);
1601: 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);
1602: PetscCall(PetscWeakFormGetJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
1603: *g0 = tmp0 ? tmp0[0] : NULL;
1604: *g1 = tmp1 ? tmp1[0] : NULL;
1605: *g2 = tmp2 ? tmp2[0] : NULL;
1606: *g3 = tmp3 ? tmp3[0] : NULL;
1607: PetscFunctionReturn(PETSC_SUCCESS);
1608: }
1610: /*@C
1611: PetscDSSetJacobian - Set the pointwise Jacobian function for given test and basis fields
1613: Not Collective
1615: Input Parameters:
1616: + ds - The `PetscDS`
1617: . f - The test field number
1618: . g - The field number
1619: . g0 - integrand for the test and basis function term
1620: . g1 - integrand for the test function and basis function gradient term
1621: . g2 - integrand for the test function gradient and basis function term
1622: - g3 - integrand for the test function gradient and basis function gradient term
1624: Calling sequence of `g0`, `g1`, `g2` and `g3`:
1625: .vb
1626: void g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1627: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1628: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1629: PetscReal t, const PetscReal x[], PetscScalar g0[])
1630: .ve
1631: + dim - the spatial dimension
1632: . Nf - the number of fields
1633: . uOff - the offset into u[] and u_t[] for each field
1634: . uOff_x - the offset into u_x[] for each field
1635: . u - each field evaluated at the current point
1636: . u_t - the time derivative of each field evaluated at the current point
1637: . u_x - the gradient of each field evaluated at the current point
1638: . aOff - the offset into a[] and a_t[] for each auxiliary field
1639: . aOff_x - the offset into a_x[] for each auxiliary field
1640: . a - each auxiliary field evaluated at the current point
1641: . a_t - the time derivative of each auxiliary field evaluated at the current point
1642: . a_x - the gradient of auxiliary each field evaluated at the current point
1643: . t - current time
1644: . u_tShift - the multiplier a for dF/dU_t
1645: . x - coordinates of the current point
1646: . numConstants - number of constant parameters
1647: . constants - constant parameters
1648: - g0 - output values at the current point
1650: Level: intermediate
1652: Note:
1653: We are using a first order FEM model for the weak form:
1654: \int_\Omega \phi g_0(u, u_t, \nabla u, x, t) \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \nabla \psi
1656: .seealso: `PetscDS`, `PetscDSGetJacobian()`
1657: @*/
1658: 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[]))
1659: {
1660: PetscFunctionBegin;
1666: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1667: PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
1668: PetscCall(PetscWeakFormSetIndexJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
1669: PetscFunctionReturn(PETSC_SUCCESS);
1670: }
1672: /*@C
1673: PetscDSUseJacobianPreconditioner - Set whether to construct a Jacobian preconditioner
1675: Not Collective
1677: Input Parameters:
1678: + prob - The `PetscDS`
1679: - useJacPre - flag that enables construction of a Jacobian preconditioner
1681: Level: intermediate
1683: .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`
1684: @*/
1685: PetscErrorCode PetscDSUseJacobianPreconditioner(PetscDS prob, PetscBool useJacPre)
1686: {
1687: PetscFunctionBegin;
1689: prob->useJacPre = useJacPre;
1690: PetscFunctionReturn(PETSC_SUCCESS);
1691: }
1693: /*@C
1694: PetscDSHasJacobianPreconditioner - Checks if a Jacobian preconditioner matrix has been set
1696: Not Collective
1698: Input Parameter:
1699: . prob - The `PetscDS`
1701: Output Parameter:
1702: . hasJacPre - flag that pointwise function for Jacobian preconditioner matrix has been set
1704: Level: intermediate
1706: .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`
1707: @*/
1708: PetscErrorCode PetscDSHasJacobianPreconditioner(PetscDS ds, PetscBool *hasJacPre)
1709: {
1710: PetscFunctionBegin;
1712: *hasJacPre = PETSC_FALSE;
1713: if (!ds->useJacPre) PetscFunctionReturn(PETSC_SUCCESS);
1714: PetscCall(PetscWeakFormHasJacobianPreconditioner(ds->wf, hasJacPre));
1715: PetscFunctionReturn(PETSC_SUCCESS);
1716: }
1718: /*@C
1719: PetscDSGetJacobianPreconditioner - Get the pointwise Jacobian preconditioner function for given test and basis field. If this is missing,
1720: the system matrix is used to build the preconditioner.
1722: Not Collective
1724: Input Parameters:
1725: + ds - The `PetscDS`
1726: . f - The test field number
1727: - g - The field number
1729: Output Parameters:
1730: + g0 - integrand for the test and basis function term
1731: . g1 - integrand for the test function and basis function gradient term
1732: . g2 - integrand for the test function gradient and basis function term
1733: - g3 - integrand for the test function gradient and basis function gradient term
1735: Calling sequence of `g0`, `g1`, `g2` and `g3`:
1736: .vb
1737: void g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1738: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1739: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1740: PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])
1741: .ve
1742: + dim - the spatial dimension
1743: . Nf - the number of fields
1744: . uOff - the offset into u[] and u_t[] for each field
1745: . uOff_x - the offset into u_x[] for each field
1746: . u - each field evaluated at the current point
1747: . u_t - the time derivative of each field evaluated at the current point
1748: . u_x - the gradient of each field evaluated at the current point
1749: . aOff - the offset into a[] and a_t[] for each auxiliary field
1750: . aOff_x - the offset into a_x[] for each auxiliary field
1751: . a - each auxiliary field evaluated at the current point
1752: . a_t - the time derivative of each auxiliary field evaluated at the current point
1753: . a_x - the gradient of auxiliary each field evaluated at the current point
1754: . t - current time
1755: . u_tShift - the multiplier a for dF/dU_t
1756: . x - coordinates of the current point
1757: . numConstants - number of constant parameters
1758: . constants - constant parameters
1759: - g0 - output values at the current point
1761: Level: intermediate
1763: Note:
1764: We are using a first order FEM model for the weak form:
1765: \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
1767: .seealso: `PetscDS`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`
1768: @*/
1769: 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[]))
1770: {
1771: PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
1772: PetscInt n0, n1, n2, n3;
1774: PetscFunctionBegin;
1776: 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);
1777: 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);
1778: PetscCall(PetscWeakFormGetJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
1779: *g0 = tmp0 ? tmp0[0] : NULL;
1780: *g1 = tmp1 ? tmp1[0] : NULL;
1781: *g2 = tmp2 ? tmp2[0] : NULL;
1782: *g3 = tmp3 ? tmp3[0] : NULL;
1783: PetscFunctionReturn(PETSC_SUCCESS);
1784: }
1786: /*@C
1787: PetscDSSetJacobianPreconditioner - Set the pointwise Jacobian preconditioner function for given test and basis fields.
1788: If this is missing, the system matrix is used to build the preconditioner.
1790: Not Collective
1792: Input Parameters:
1793: + ds - The `PetscDS`
1794: . f - The test field number
1795: . g - The field number
1796: . g0 - integrand for the test and basis function term
1797: . g1 - integrand for the test function and basis function gradient term
1798: . g2 - integrand for the test function gradient and basis function term
1799: - g3 - integrand for the test function gradient and basis function gradient term
1801: Calling sequence of `g0`, `g1`, `g2` and `g3`:
1802: .vb
1803: void g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1804: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1805: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1806: PetscReal t, const PetscReal x[], PetscScalar g0[])
1807: .ve
1808: + dim - the spatial dimension
1809: . Nf - the number of fields
1810: . uOff - the offset into u[] and u_t[] for each field
1811: . uOff_x - the offset into u_x[] for each field
1812: . u - each field evaluated at the current point
1813: . u_t - the time derivative of each field evaluated at the current point
1814: . u_x - the gradient of each field evaluated at the current point
1815: . aOff - the offset into a[] and a_t[] for each auxiliary field
1816: . aOff_x - the offset into a_x[] for each auxiliary field
1817: . a - each auxiliary field evaluated at the current point
1818: . a_t - the time derivative of each auxiliary field evaluated at the current point
1819: . a_x - the gradient of auxiliary each field evaluated at the current point
1820: . t - current time
1821: . u_tShift - the multiplier a for dF/dU_t
1822: . x - coordinates of the current point
1823: . numConstants - number of constant parameters
1824: . constants - constant parameters
1825: - g0 - output values at the current point
1827: Level: intermediate
1829: Note:
1830: We are using a first order FEM model for the weak form:
1831: \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
1833: .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobian()`
1834: @*/
1835: 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[]))
1836: {
1837: PetscFunctionBegin;
1843: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1844: PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
1845: PetscCall(PetscWeakFormSetIndexJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
1846: PetscFunctionReturn(PETSC_SUCCESS);
1847: }
1849: /*@C
1850: PetscDSHasDynamicJacobian - Signals that a dynamic Jacobian, dF/du_t, has been set
1852: Not Collective
1854: Input Parameter:
1855: . ds - The `PetscDS`
1857: Output Parameter:
1858: . hasDynJac - flag that pointwise function for dynamic Jacobian has been set
1860: Level: intermediate
1862: .seealso: `PetscDS`, `PetscDSGetDynamicJacobian()`, `PetscDSSetDynamicJacobian()`, `PetscDSGetJacobian()`
1863: @*/
1864: PetscErrorCode PetscDSHasDynamicJacobian(PetscDS ds, PetscBool *hasDynJac)
1865: {
1866: PetscFunctionBegin;
1868: PetscCall(PetscWeakFormHasDynamicJacobian(ds->wf, hasDynJac));
1869: PetscFunctionReturn(PETSC_SUCCESS);
1870: }
1872: /*@C
1873: PetscDSGetDynamicJacobian - Get the pointwise dynamic Jacobian, dF/du_t, function for given test and basis field
1875: Not Collective
1877: Input Parameters:
1878: + ds - The `PetscDS`
1879: . f - The test field number
1880: - g - The field number
1882: Output Parameters:
1883: + g0 - integrand for the test and basis function term
1884: . g1 - integrand for the test function and basis function gradient term
1885: . g2 - integrand for the test function gradient and basis function term
1886: - g3 - integrand for the test function gradient and basis function gradient term
1888: Calling sequence of `g0`, `g1`, `g2` and `g3`:
1889: .vb
1890: void g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1891: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1892: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1893: PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[])
1894: .ve
1895: + dim - the spatial dimension
1896: . Nf - the number of fields
1897: . uOff - the offset into u[] and u_t[] for each field
1898: . uOff_x - the offset into u_x[] for each field
1899: . u - each field evaluated at the current point
1900: . u_t - the time derivative of each field evaluated at the current point
1901: . u_x - the gradient of each field evaluated at the current point
1902: . aOff - the offset into a[] and a_t[] for each auxiliary field
1903: . aOff_x - the offset into a_x[] for each auxiliary field
1904: . a - each auxiliary field evaluated at the current point
1905: . a_t - the time derivative of each auxiliary field evaluated at the current point
1906: . a_x - the gradient of auxiliary each field evaluated at the current point
1907: . t - current time
1908: . u_tShift - the multiplier a for dF/dU_t
1909: . x - coordinates of the current point
1910: . numConstants - number of constant parameters
1911: . constants - constant parameters
1912: - g0 - output values at the current point
1914: Level: intermediate
1916: Note:
1917: We are using a first order FEM model for the weak form:
1918: \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
1920: .seealso: `PetscDS`, `PetscDSSetJacobian()`
1921: @*/
1922: 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[]))
1923: {
1924: PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3;
1925: PetscInt n0, n1, n2, n3;
1927: PetscFunctionBegin;
1929: 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);
1930: 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);
1931: PetscCall(PetscWeakFormGetDynamicJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
1932: *g0 = tmp0 ? tmp0[0] : NULL;
1933: *g1 = tmp1 ? tmp1[0] : NULL;
1934: *g2 = tmp2 ? tmp2[0] : NULL;
1935: *g3 = tmp3 ? tmp3[0] : NULL;
1936: PetscFunctionReturn(PETSC_SUCCESS);
1937: }
1939: /*@C
1940: PetscDSSetDynamicJacobian - Set the pointwise dynamic Jacobian, dF/du_t, function for given test and basis fields
1942: Not Collective
1944: Input Parameters:
1945: + ds - The `PetscDS`
1946: . f - The test field number
1947: . g - The field number
1948: . g0 - integrand for the test and basis function term
1949: . g1 - integrand for the test function and basis function gradient term
1950: . g2 - integrand for the test function gradient and basis function term
1951: - g3 - integrand for the test function gradient and basis function gradient term
1953: Calling sequence of `g0`, `g1`, `g2` and `g3`:
1954: .vb
1955: void g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
1956: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
1957: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
1958: PetscReal t, const PetscReal x[], PetscScalar g0[])
1959: .ve
1960: + dim - the spatial dimension
1961: . Nf - the number of fields
1962: . uOff - the offset into u[] and u_t[] for each field
1963: . uOff_x - the offset into u_x[] for each field
1964: . u - each field evaluated at the current point
1965: . u_t - the time derivative of each field evaluated at the current point
1966: . u_x - the gradient of each field evaluated at the current point
1967: . aOff - the offset into a[] and a_t[] for each auxiliary field
1968: . aOff_x - the offset into a_x[] for each auxiliary field
1969: . a - each auxiliary field evaluated at the current point
1970: . a_t - the time derivative of each auxiliary field evaluated at the current point
1971: . a_x - the gradient of auxiliary each field evaluated at the current point
1972: . t - current time
1973: . u_tShift - the multiplier a for dF/dU_t
1974: . x - coordinates of the current point
1975: . numConstants - number of constant parameters
1976: . constants - constant parameters
1977: - g0 - output values at the current point
1979: Level: intermediate
1981: Note:
1982: We are using a first order FEM model for the weak form:
1983: \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
1985: .seealso: `PetscDS`, `PetscDSGetJacobian()`
1986: @*/
1987: 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[]))
1988: {
1989: PetscFunctionBegin;
1995: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1996: PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
1997: PetscCall(PetscWeakFormSetIndexDynamicJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
1998: PetscFunctionReturn(PETSC_SUCCESS);
1999: }
2001: /*@C
2002: PetscDSGetRiemannSolver - Returns the Riemann solver for the given field
2004: Not Collective
2006: Input Parameters:
2007: + ds - The `PetscDS` object
2008: - f - The field number
2010: Output Parameter:
2011: . r - Riemann solver
2013: Calling sequence of `r`:
2014: .vb
2015: void r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx)
2016: .ve
2017: + dim - The spatial dimension
2018: . Nf - The number of fields
2019: . x - The coordinates at a point on the interface
2020: . n - The normal vector to the interface
2021: . uL - The state vector to the left of the interface
2022: . uR - The state vector to the right of the interface
2023: . flux - output array of flux through the interface
2024: . numConstants - number of constant parameters
2025: . constants - constant parameters
2026: - ctx - optional user context
2028: Level: intermediate
2030: .seealso: `PetscDS`, `PetscDSSetRiemannSolver()`
2031: @*/
2032: 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))
2033: {
2034: PetscRiemannFunc *tmp;
2035: PetscInt n;
2037: PetscFunctionBegin;
2040: 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);
2041: PetscCall(PetscWeakFormGetRiemannSolver(ds->wf, NULL, 0, f, 0, &n, &tmp));
2042: *r = tmp ? tmp[0] : NULL;
2043: PetscFunctionReturn(PETSC_SUCCESS);
2044: }
2046: /*@C
2047: PetscDSSetRiemannSolver - Sets the Riemann solver for the given field
2049: Not Collective
2051: Input Parameters:
2052: + ds - The `PetscDS` object
2053: . f - The field number
2054: - r - Riemann solver
2056: Calling sequence of `r`:
2057: .vb
2058: void r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx)
2059: .ve
2060: + dim - The spatial dimension
2061: . Nf - The number of fields
2062: . x - The coordinates at a point on the interface
2063: . n - The normal vector to the interface
2064: . uL - The state vector to the left of the interface
2065: . uR - The state vector to the right of the interface
2066: . flux - output array of flux through the interface
2067: . numConstants - number of constant parameters
2068: . constants - constant parameters
2069: - ctx - optional user context
2071: Level: intermediate
2073: .seealso: `PetscDS`, `PetscDSGetRiemannSolver()`
2074: @*/
2075: 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))
2076: {
2077: PetscFunctionBegin;
2080: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2081: PetscCall(PetscWeakFormSetIndexRiemannSolver(ds->wf, NULL, 0, f, 0, 0, r));
2082: PetscFunctionReturn(PETSC_SUCCESS);
2083: }
2085: /*@C
2086: PetscDSGetUpdate - Get the pointwise update function for a given field
2088: Not Collective
2090: Input Parameters:
2091: + ds - The `PetscDS`
2092: - f - The field number
2094: Output Parameter:
2095: . update - update function
2097: Calling sequence of `update`:
2098: .vb
2099: void update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2100: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2101: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2102: PetscReal t, const PetscReal x[], PetscScalar uNew[])
2103: .ve
2104: + dim - the spatial dimension
2105: . Nf - the number of fields
2106: . uOff - the offset into u[] and u_t[] for each field
2107: . uOff_x - the offset into u_x[] for each field
2108: . u - each field evaluated at the current point
2109: . u_t - the time derivative of each field evaluated at the current point
2110: . u_x - the gradient of each field evaluated at the current point
2111: . aOff - the offset into a[] and a_t[] for each auxiliary field
2112: . aOff_x - the offset into a_x[] for each auxiliary field
2113: . a - each auxiliary field evaluated at the current point
2114: . a_t - the time derivative of each auxiliary field evaluated at the current point
2115: . a_x - the gradient of auxiliary each field evaluated at the current point
2116: . t - current time
2117: . x - coordinates of the current point
2118: - uNew - new value for field at the current point
2120: Level: intermediate
2122: .seealso: `PetscDS`, `PetscDSSetUpdate()`, `PetscDSSetResidual()`
2123: @*/
2124: 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[]))
2125: {
2126: PetscFunctionBegin;
2128: 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);
2129: if (update) {
2131: *update = ds->update[f];
2132: }
2133: PetscFunctionReturn(PETSC_SUCCESS);
2134: }
2136: /*@C
2137: PetscDSSetUpdate - Set the pointwise update function for a given field
2139: Not Collective
2141: Input Parameters:
2142: + ds - The `PetscDS`
2143: . f - The field number
2144: - update - update function
2146: Calling sequence of `update`:
2147: .vb
2148: void update(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2149: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2150: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2151: PetscReal t, const PetscReal x[], PetscScalar uNew[])
2152: .ve
2153: + dim - the spatial dimension
2154: . Nf - the number of fields
2155: . uOff - the offset into u[] and u_t[] for each field
2156: . uOff_x - the offset into u_x[] for each field
2157: . u - each field evaluated at the current point
2158: . u_t - the time derivative of each field evaluated at the current point
2159: . u_x - the gradient of each field evaluated at the current point
2160: . aOff - the offset into a[] and a_t[] for each auxiliary field
2161: . aOff_x - the offset into a_x[] for each auxiliary field
2162: . a - each auxiliary field evaluated at the current point
2163: . a_t - the time derivative of each auxiliary field evaluated at the current point
2164: . a_x - the gradient of auxiliary each field evaluated at the current point
2165: . t - current time
2166: . x - coordinates of the current point
2167: - uNew - new field values at the current point
2169: Level: intermediate
2171: .seealso: `PetscDS`, `PetscDSGetResidual()`
2172: @*/
2173: 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[]))
2174: {
2175: PetscFunctionBegin;
2178: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2179: PetscCall(PetscDSEnlarge_Static(ds, f + 1));
2180: ds->update[f] = update;
2181: PetscFunctionReturn(PETSC_SUCCESS);
2182: }
2184: PetscErrorCode PetscDSGetContext(PetscDS ds, PetscInt f, void *ctx)
2185: {
2186: PetscFunctionBegin;
2188: 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);
2190: *(void **)ctx = ds->ctx[f];
2191: PetscFunctionReturn(PETSC_SUCCESS);
2192: }
2194: PetscErrorCode PetscDSSetContext(PetscDS ds, PetscInt f, void *ctx)
2195: {
2196: PetscFunctionBegin;
2198: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2199: PetscCall(PetscDSEnlarge_Static(ds, f + 1));
2200: ds->ctx[f] = ctx;
2201: PetscFunctionReturn(PETSC_SUCCESS);
2202: }
2204: /*@C
2205: PetscDSGetBdResidual - Get the pointwise boundary residual function for a given test field
2207: Not Collective
2209: Input Parameters:
2210: + ds - The PetscDS
2211: - f - The test field number
2213: Output Parameters:
2214: + f0 - boundary integrand for the test function term
2215: - f1 - boundary integrand for the test function gradient term
2217: Calling sequence of `f0` and `f1`:
2218: .vb
2219: void f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2220: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2221: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2222: PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])
2223: .ve
2224: + dim - the spatial dimension
2225: . Nf - the number of fields
2226: . uOff - the offset into u[] and u_t[] for each field
2227: . uOff_x - the offset into u_x[] for each field
2228: . u - each field evaluated at the current point
2229: . u_t - the time derivative of each field evaluated at the current point
2230: . u_x - the gradient of each field evaluated at the current point
2231: . aOff - the offset into a[] and a_t[] for each auxiliary field
2232: . aOff_x - the offset into a_x[] for each auxiliary field
2233: . a - each auxiliary field evaluated at the current point
2234: . a_t - the time derivative of each auxiliary field evaluated at the current point
2235: . a_x - the gradient of auxiliary each field evaluated at the current point
2236: . t - current time
2237: . x - coordinates of the current point
2238: . n - unit normal at the current point
2239: . numConstants - number of constant parameters
2240: . constants - constant parameters
2241: - f0 - output values at the current point
2243: Level: intermediate
2245: Note:
2246: We are using a first order FEM model for the weak form:
2247: \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
2249: .seealso: `PetscDS`, `PetscDSSetBdResidual()`
2250: @*/
2251: 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[]))
2252: {
2253: PetscBdPointFunc *tmp0, *tmp1;
2254: PetscInt n0, n1;
2256: PetscFunctionBegin;
2258: 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);
2259: PetscCall(PetscWeakFormGetBdResidual(ds->wf, NULL, 0, f, 0, &n0, &tmp0, &n1, &tmp1));
2260: *f0 = tmp0 ? tmp0[0] : NULL;
2261: *f1 = tmp1 ? tmp1[0] : NULL;
2262: PetscFunctionReturn(PETSC_SUCCESS);
2263: }
2265: /*@C
2266: PetscDSSetBdResidual - Get the pointwise boundary residual function for a given test field
2268: Not Collective
2270: Input Parameters:
2271: + ds - The `PetscDS`
2272: . f - The test field number
2273: . f0 - boundary integrand for the test function term
2274: - f1 - boundary integrand for the test function gradient term
2276: Calling sequence of `f0` and `f1`:
2277: .vb
2278: void f0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2279: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2280: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2281: PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[])
2282: .ve
2283: + dim - the spatial dimension
2284: . Nf - the number of fields
2285: . uOff - the offset into u[] and u_t[] for each field
2286: . uOff_x - the offset into u_x[] for each field
2287: . u - each field evaluated at the current point
2288: . u_t - the time derivative of each field evaluated at the current point
2289: . u_x - the gradient of each field evaluated at the current point
2290: . aOff - the offset into a[] and a_t[] for each auxiliary field
2291: . aOff_x - the offset into a_x[] for each auxiliary field
2292: . a - each auxiliary field evaluated at the current point
2293: . a_t - the time derivative of each auxiliary field evaluated at the current point
2294: . a_x - the gradient of auxiliary each field evaluated at the current point
2295: . t - current time
2296: . x - coordinates of the current point
2297: . n - unit normal at the current point
2298: . numConstants - number of constant parameters
2299: . constants - constant parameters
2300: - f0 - output values at the current point
2302: Level: intermediate
2304: Note:
2305: We are using a first order FEM model for the weak form:
2306: \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
2308: .seealso: `PetscDS`, `PetscDSGetBdResidual()`
2309: @*/
2310: 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[]))
2311: {
2312: PetscFunctionBegin;
2314: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2315: PetscCall(PetscWeakFormSetIndexBdResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1));
2316: PetscFunctionReturn(PETSC_SUCCESS);
2317: }
2319: /*@
2320: PetscDSHasBdJacobian - Indicates that boundary Jacobian functions have been set
2322: Not Collective
2324: Input Parameter:
2325: . ds - The `PetscDS`
2327: Output Parameter:
2328: . hasBdJac - flag that pointwise function for the boundary Jacobian has been set
2330: Level: intermediate
2332: .seealso: `PetscDS`, `PetscDSHasJacobian()`, `PetscDSSetBdJacobian()`, `PetscDSGetBdJacobian()`
2333: @*/
2334: PetscErrorCode PetscDSHasBdJacobian(PetscDS ds, PetscBool *hasBdJac)
2335: {
2336: PetscFunctionBegin;
2339: PetscCall(PetscWeakFormHasBdJacobian(ds->wf, hasBdJac));
2340: PetscFunctionReturn(PETSC_SUCCESS);
2341: }
2343: /*@C
2344: PetscDSGetBdJacobian - Get the pointwise boundary Jacobian function for given test and basis field
2346: Not Collective
2348: Input Parameters:
2349: + ds - The `PetscDS`
2350: . f - The test field number
2351: - g - The field number
2353: Output Parameters:
2354: + g0 - integrand for the test and basis function term
2355: . g1 - integrand for the test function and basis function gradient term
2356: . g2 - integrand for the test function gradient and basis function term
2357: - g3 - integrand for the test function gradient and basis function gradient term
2359: Calling sequence of `g0`, `g1`, `g2` and `g3`:
2360: .vb
2361: void g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2362: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2363: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2364: PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[])
2365: .ve
2366: + dim - the spatial dimension
2367: . Nf - the number of fields
2368: . uOff - the offset into u[] and u_t[] for each field
2369: . uOff_x - the offset into u_x[] for each field
2370: . u - each field evaluated at the current point
2371: . u_t - the time derivative of each field evaluated at the current point
2372: . u_x - the gradient of each field evaluated at the current point
2373: . aOff - the offset into a[] and a_t[] for each auxiliary field
2374: . aOff_x - the offset into a_x[] for each auxiliary field
2375: . a - each auxiliary field evaluated at the current point
2376: . a_t - the time derivative of each auxiliary field evaluated at the current point
2377: . a_x - the gradient of auxiliary each field evaluated at the current point
2378: . t - current time
2379: . u_tShift - the multiplier a for dF/dU_t
2380: . x - coordinates of the current point
2381: . n - normal at the current point
2382: . numConstants - number of constant parameters
2383: . constants - constant parameters
2384: - g0 - output values at the current point
2386: Level: intermediate
2388: Note:
2389: We are using a first order FEM model for the weak form:
2390: \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
2392: .seealso: `PetscDS`, `PetscDSSetBdJacobian()`
2393: @*/
2394: 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[]))
2395: {
2396: PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3;
2397: PetscInt n0, n1, n2, n3;
2399: PetscFunctionBegin;
2401: 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);
2402: 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);
2403: PetscCall(PetscWeakFormGetBdJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
2404: *g0 = tmp0 ? tmp0[0] : NULL;
2405: *g1 = tmp1 ? tmp1[0] : NULL;
2406: *g2 = tmp2 ? tmp2[0] : NULL;
2407: *g3 = tmp3 ? tmp3[0] : NULL;
2408: PetscFunctionReturn(PETSC_SUCCESS);
2409: }
2411: /*@C
2412: PetscDSSetBdJacobian - Set the pointwise boundary Jacobian function for given test and basis field
2414: Not Collective
2416: Input Parameters:
2417: + ds - The PetscDS
2418: . f - The test field number
2419: . g - The field number
2420: . g0 - integrand for the test and basis function term
2421: . g1 - integrand for the test function and basis function gradient term
2422: . g2 - integrand for the test function gradient and basis function term
2423: - g3 - integrand for the test function gradient and basis function gradient term
2425: Calling sequence of `g0`, `g1`, `g2` and `g3`:
2426: .vb
2427: void g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2428: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2429: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2430: PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[])
2431: .ve
2432: + dim - the spatial dimension
2433: . Nf - the number of fields
2434: . uOff - the offset into u[] and u_t[] for each field
2435: . uOff_x - the offset into u_x[] for each field
2436: . u - each field evaluated at the current point
2437: . u_t - the time derivative of each field evaluated at the current point
2438: . u_x - the gradient of each field evaluated at the current point
2439: . aOff - the offset into a[] and a_t[] for each auxiliary field
2440: . aOff_x - the offset into a_x[] for each auxiliary field
2441: . a - each auxiliary field evaluated at the current point
2442: . a_t - the time derivative of each auxiliary field evaluated at the current point
2443: . a_x - the gradient of auxiliary each field evaluated at the current point
2444: . t - current time
2445: . u_tShift - the multiplier a for dF/dU_t
2446: . x - coordinates of the current point
2447: . n - normal at the current point
2448: . numConstants - number of constant parameters
2449: . constants - constant parameters
2450: - g0 - output values at the current point
2452: Level: intermediate
2454: Note:
2455: We are using a first order FEM model for the weak form:
2456: \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
2458: .seealso: `PetscDS`, `PetscDSGetBdJacobian()`
2459: @*/
2460: 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[]))
2461: {
2462: PetscFunctionBegin;
2468: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2469: PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
2470: PetscCall(PetscWeakFormSetIndexBdJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
2471: PetscFunctionReturn(PETSC_SUCCESS);
2472: }
2474: /*@
2475: PetscDSHasBdJacobianPreconditioner - Signals that boundary Jacobian preconditioner functions have been set
2477: Not Collective
2479: Input Parameter:
2480: . ds - The `PetscDS`
2482: Output Parameter:
2483: . hasBdJac - flag that pointwise function for the boundary Jacobian preconditioner has been set
2485: Level: intermediate
2487: .seealso: `PetscDS`, `PetscDSHasJacobian()`, `PetscDSSetBdJacobian()`, `PetscDSGetBdJacobian()`
2488: @*/
2489: PetscErrorCode PetscDSHasBdJacobianPreconditioner(PetscDS ds, PetscBool *hasBdJacPre)
2490: {
2491: PetscFunctionBegin;
2494: PetscCall(PetscWeakFormHasBdJacobianPreconditioner(ds->wf, hasBdJacPre));
2495: PetscFunctionReturn(PETSC_SUCCESS);
2496: }
2498: /*@C
2499: PetscDSGetBdJacobianPreconditioner - Get the pointwise boundary Jacobian preconditioner function for given test and basis field
2501: Not Collective; No Fortran Support
2503: Input Parameters:
2504: + ds - The `PetscDS`
2505: . f - The test field number
2506: - g - The field number
2508: Output Parameters:
2509: + g0 - integrand for the test and basis function term
2510: . g1 - integrand for the test function and basis function gradient term
2511: . g2 - integrand for the test function gradient and basis function term
2512: - g3 - integrand for the test function gradient and basis function gradient term
2514: Calling sequence of `g0`, `g1`, `g2` and `g3`:
2515: .vb
2516: void g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2517: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2518: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2519: PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
2520: .ve
2521: + dim - the spatial dimension
2522: . Nf - the number of fields
2523: . NfAux - the number of auxiliary fields
2524: . uOff - the offset into u[] and u_t[] for each field
2525: . uOff_x - the offset into u_x[] for each field
2526: . u - each field evaluated at the current point
2527: . u_t - the time derivative of each field evaluated at the current point
2528: . u_x - the gradient of each field evaluated at the current point
2529: . aOff - the offset into a[] and a_t[] for each auxiliary field
2530: . aOff_x - the offset into a_x[] for each auxiliary field
2531: . a - each auxiliary field evaluated at the current point
2532: . a_t - the time derivative of each auxiliary field evaluated at the current point
2533: . a_x - the gradient of auxiliary each field evaluated at the current point
2534: . t - current time
2535: . u_tShift - the multiplier a for dF/dU_t
2536: . x - coordinates of the current point
2537: . n - normal at the current point
2538: . numConstants - number of constant parameters
2539: . constants - constant parameters
2540: - g0 - output values at the current point
2542: Level: intermediate
2544: Note:
2545: We are using a first order FEM model for the weak form:
2546: \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
2548: .seealso: `PetscDS`, `PetscDSSetBdJacobianPreconditioner()`
2549: @*/
2550: 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[]))
2551: {
2552: PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3;
2553: PetscInt n0, n1, n2, n3;
2555: PetscFunctionBegin;
2557: 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);
2558: 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);
2559: PetscCall(PetscWeakFormGetBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
2560: *g0 = tmp0 ? tmp0[0] : NULL;
2561: *g1 = tmp1 ? tmp1[0] : NULL;
2562: *g2 = tmp2 ? tmp2[0] : NULL;
2563: *g3 = tmp3 ? tmp3[0] : NULL;
2564: PetscFunctionReturn(PETSC_SUCCESS);
2565: }
2567: /*@C
2568: PetscDSSetBdJacobianPreconditioner - Set the pointwise boundary Jacobian preconditioner function for given test and basis field
2570: Not Collective; No Fortran Support
2572: Input Parameters:
2573: + ds - The `PetscDS`
2574: . f - The test field number
2575: . g - The field number
2576: . g0 - integrand for the test and basis function term
2577: . g1 - integrand for the test function and basis function gradient term
2578: . g2 - integrand for the test function gradient and basis function term
2579: - g3 - integrand for the test function gradient and basis function gradient term
2581: Calling sequence of `g0`, `g1`, `g2` and `g3`:
2582: .vb
2583: void g0(PetscInt dim, PetscInt Nf, PetscInt NfAux,
2584: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
2585: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
2586: PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
2587: .ve
2588: + dim - the spatial dimension
2589: . Nf - the number of fields
2590: . NfAux - the number of auxiliary fields
2591: . uOff - the offset into u[] and u_t[] for each field
2592: . uOff_x - the offset into u_x[] for each field
2593: . u - each field evaluated at the current point
2594: . u_t - the time derivative of each field evaluated at the current point
2595: . u_x - the gradient of each field evaluated at the current point
2596: . aOff - the offset into a[] and a_t[] for each auxiliary field
2597: . aOff_x - the offset into a_x[] for each auxiliary field
2598: . a - each auxiliary field evaluated at the current point
2599: . a_t - the time derivative of each auxiliary field evaluated at the current point
2600: . a_x - the gradient of auxiliary each field evaluated at the current point
2601: . t - current time
2602: . u_tShift - the multiplier a for dF/dU_t
2603: . x - coordinates of the current point
2604: . n - normal at the current point
2605: . numConstants - number of constant parameters
2606: . constants - constant parameters
2607: - g0 - output values at the current point
2609: Level: intermediate
2611: Note:
2612: We are using a first order FEM model for the weak form:
2613: \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
2615: .seealso: `PetscDS`, `PetscDSGetBdJacobianPreconditioner()`
2616: @*/
2617: 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[]))
2618: {
2619: PetscFunctionBegin;
2625: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2626: PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
2627: PetscCall(PetscWeakFormSetIndexBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
2628: PetscFunctionReturn(PETSC_SUCCESS);
2629: }
2631: /*@C
2632: PetscDSGetExactSolution - Get the pointwise exact solution function for a given test field
2634: Not Collective
2636: Input Parameters:
2637: + prob - The PetscDS
2638: - f - The test field number
2640: Output Parameters:
2641: + exactSol - exact solution for the test field
2642: - exactCtx - exact solution context
2644: Calling sequence of `exactSol`:
2645: .vb
2646: PetscErrorCode sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2647: .ve
2648: + dim - the spatial dimension
2649: . t - current time
2650: . x - coordinates of the current point
2651: . Nc - the number of field components
2652: . u - the solution field evaluated at the current point
2653: - ctx - a user context
2655: Level: intermediate
2657: .seealso: `PetscDS`, `PetscDSSetExactSolution()`, `PetscDSGetExactSolutionTimeDerivative()`
2658: @*/
2659: PetscErrorCode PetscDSGetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx)
2660: {
2661: PetscFunctionBegin;
2663: 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);
2664: if (sol) {
2666: *sol = prob->exactSol[f];
2667: }
2668: if (ctx) {
2670: *ctx = prob->exactCtx[f];
2671: }
2672: PetscFunctionReturn(PETSC_SUCCESS);
2673: }
2675: /*@C
2676: PetscDSSetExactSolution - Set the pointwise exact solution function for a given test field
2678: Not Collective
2680: Input Parameters:
2681: + prob - The `PetscDS`
2682: . f - The test field number
2683: . sol - solution function for the test fields
2684: - ctx - solution context or `NULL`
2686: Calling sequence of `sol`:
2687: .vb
2688: PetscErrorCode sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2689: .ve
2690: + dim - the spatial dimension
2691: . t - current time
2692: . x - coordinates of the current point
2693: . Nc - the number of field components
2694: . u - the solution field evaluated at the current point
2695: - ctx - a user context
2697: Level: intermediate
2699: .seealso: `PetscDS`, `PetscDSGetExactSolution()`
2700: @*/
2701: PetscErrorCode PetscDSSetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx)
2702: {
2703: PetscFunctionBegin;
2705: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2706: PetscCall(PetscDSEnlarge_Static(prob, f + 1));
2707: if (sol) {
2709: prob->exactSol[f] = sol;
2710: }
2711: if (ctx) {
2713: prob->exactCtx[f] = ctx;
2714: }
2715: PetscFunctionReturn(PETSC_SUCCESS);
2716: }
2718: /*@C
2719: PetscDSGetExactSolutionTimeDerivative - Get the pointwise time derivative of the exact solution function for a given test field
2721: Not Collective
2723: Input Parameters:
2724: + prob - The `PetscDS`
2725: - f - The test field number
2727: Output Parameters:
2728: + exactSol - time derivative of the exact solution for the test field
2729: - exactCtx - time derivative of the exact solution context
2731: Calling sequence of `exactSol`:
2732: .vb
2733: PetscErrorCode sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2734: .ve
2735: + dim - the spatial dimension
2736: . t - current time
2737: . x - coordinates of the current point
2738: . Nc - the number of field components
2739: . u - the solution field evaluated at the current point
2740: - ctx - a user context
2742: Level: intermediate
2744: .seealso: `PetscDS`, `PetscDSSetExactSolutionTimeDerivative()`, `PetscDSGetExactSolution()`
2745: @*/
2746: PetscErrorCode PetscDSGetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx)
2747: {
2748: PetscFunctionBegin;
2750: 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);
2751: if (sol) {
2753: *sol = prob->exactSol_t[f];
2754: }
2755: if (ctx) {
2757: *ctx = prob->exactCtx_t[f];
2758: }
2759: PetscFunctionReturn(PETSC_SUCCESS);
2760: }
2762: /*@C
2763: PetscDSSetExactSolutionTimeDerivative - Set the pointwise time derivative of the exact solution function for a given test field
2765: Not Collective
2767: Input Parameters:
2768: + prob - The `PetscDS`
2769: . f - The test field number
2770: . sol - time derivative of the solution function for the test fields
2771: - ctx - time derivative of the solution context or `NULL`
2773: Calling sequence of `sol`:
2774: .vb
2775: PetscErrorCode sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx)
2776: .ve
2777: + dim - the spatial dimension
2778: . t - current time
2779: . x - coordinates of the current point
2780: . Nc - the number of field components
2781: . u - the solution field evaluated at the current point
2782: - ctx - a user context
2784: Level: intermediate
2786: .seealso: `PetscDS`, `PetscDSGetExactSolutionTimeDerivative()`, `PetscDSSetExactSolution()`
2787: @*/
2788: PetscErrorCode PetscDSSetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx)
2789: {
2790: PetscFunctionBegin;
2792: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2793: PetscCall(PetscDSEnlarge_Static(prob, f + 1));
2794: if (sol) {
2796: prob->exactSol_t[f] = sol;
2797: }
2798: if (ctx) {
2800: prob->exactCtx_t[f] = ctx;
2801: }
2802: PetscFunctionReturn(PETSC_SUCCESS);
2803: }
2805: /*@C
2806: PetscDSGetConstants - Returns the array of constants passed to point functions
2808: Not Collective
2810: Input Parameter:
2811: . prob - The `PetscDS` object
2813: Output Parameters:
2814: + numConstants - The number of constants
2815: - constants - The array of constants, NULL if there are none
2817: Level: intermediate
2819: .seealso: `PetscDS`, `PetscDSSetConstants()`, `PetscDSCreate()`
2820: @*/
2821: PetscErrorCode PetscDSGetConstants(PetscDS prob, PetscInt *numConstants, const PetscScalar *constants[])
2822: {
2823: PetscFunctionBegin;
2825: if (numConstants) {
2827: *numConstants = prob->numConstants;
2828: }
2829: if (constants) {
2831: *constants = prob->constants;
2832: }
2833: PetscFunctionReturn(PETSC_SUCCESS);
2834: }
2836: /*@C
2837: PetscDSSetConstants - Set the array of constants passed to point functions
2839: Not Collective
2841: Input Parameters:
2842: + prob - The `PetscDS` object
2843: . numConstants - The number of constants
2844: - constants - The array of constants, NULL if there are none
2846: Level: intermediate
2848: .seealso: `PetscDS`, `PetscDSGetConstants()`, `PetscDSCreate()`
2849: @*/
2850: PetscErrorCode PetscDSSetConstants(PetscDS prob, PetscInt numConstants, PetscScalar constants[])
2851: {
2852: PetscFunctionBegin;
2854: if (numConstants != prob->numConstants) {
2855: PetscCall(PetscFree(prob->constants));
2856: prob->numConstants = numConstants;
2857: if (prob->numConstants) {
2858: PetscCall(PetscMalloc1(prob->numConstants, &prob->constants));
2859: } else {
2860: prob->constants = NULL;
2861: }
2862: }
2863: if (prob->numConstants) {
2865: PetscCall(PetscArraycpy(prob->constants, constants, prob->numConstants));
2866: }
2867: PetscFunctionReturn(PETSC_SUCCESS);
2868: }
2870: /*@
2871: PetscDSGetFieldIndex - Returns the index of the given field
2873: Not Collective
2875: Input Parameters:
2876: + prob - The `PetscDS` object
2877: - disc - The discretization object
2879: Output Parameter:
2880: . f - The field number
2882: Level: beginner
2884: .seealso: `PetscDS`, `PetscGetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2885: @*/
2886: PetscErrorCode PetscDSGetFieldIndex(PetscDS prob, PetscObject disc, PetscInt *f)
2887: {
2888: PetscInt g;
2890: PetscFunctionBegin;
2893: *f = -1;
2894: for (g = 0; g < prob->Nf; ++g) {
2895: if (disc == prob->disc[g]) break;
2896: }
2897: PetscCheck(g != prob->Nf, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Field not found in PetscDS.");
2898: *f = g;
2899: PetscFunctionReturn(PETSC_SUCCESS);
2900: }
2902: /*@
2903: PetscDSGetFieldSize - Returns the size of the given field in the full space basis
2905: Not Collective
2907: Input Parameters:
2908: + prob - The `PetscDS` object
2909: - f - The field number
2911: Output Parameter:
2912: . size - The size
2914: Level: beginner
2916: .seealso: `PetscDS`, `PetscDSGetFieldOffset()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2917: @*/
2918: PetscErrorCode PetscDSGetFieldSize(PetscDS prob, PetscInt f, PetscInt *size)
2919: {
2920: PetscFunctionBegin;
2923: 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);
2924: PetscCall(PetscDSSetUp(prob));
2925: *size = prob->Nb[f];
2926: PetscFunctionReturn(PETSC_SUCCESS);
2927: }
2929: /*@
2930: PetscDSGetFieldOffset - Returns the offset of the given field in the full space basis
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`, `PetscDSGetFieldSize()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2944: @*/
2945: PetscErrorCode PetscDSGetFieldOffset(PetscDS prob, PetscInt f, PetscInt *off)
2946: {
2947: PetscInt size, g;
2949: PetscFunctionBegin;
2952: 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);
2953: *off = 0;
2954: for (g = 0; g < f; ++g) {
2955: PetscCall(PetscDSGetFieldSize(prob, g, &size));
2956: *off += size;
2957: }
2958: PetscFunctionReturn(PETSC_SUCCESS);
2959: }
2961: /*@
2962: PetscDSGetFieldOffsetCohesive - Returns the offset of the given field in the full space basis on a cohesive cell
2964: Not Collective
2966: Input Parameters:
2967: + prob - The `PetscDS` object
2968: - f - The field number
2970: Output Parameter:
2971: . off - The offset
2973: Level: beginner
2975: .seealso: `PetscDS`, `PetscDSGetFieldSize()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2976: @*/
2977: PetscErrorCode PetscDSGetFieldOffsetCohesive(PetscDS ds, PetscInt f, PetscInt *off)
2978: {
2979: PetscInt size, g;
2981: PetscFunctionBegin;
2984: 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);
2985: *off = 0;
2986: for (g = 0; g < f; ++g) {
2987: PetscBool cohesive;
2989: PetscCall(PetscDSGetCohesive(ds, g, &cohesive));
2990: PetscCall(PetscDSGetFieldSize(ds, g, &size));
2991: *off += cohesive ? size : size * 2;
2992: }
2993: PetscFunctionReturn(PETSC_SUCCESS);
2994: }
2996: /*@
2997: PetscDSGetDimensions - Returns the size of the approximation space for each field on an evaluation point
2999: Not Collective
3001: Input Parameter:
3002: . prob - The `PetscDS` object
3004: Output Parameter:
3005: . dimensions - The number of dimensions
3007: Level: beginner
3009: .seealso: `PetscDS`, `PetscDSGetComponentOffsets()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
3010: @*/
3011: PetscErrorCode PetscDSGetDimensions(PetscDS prob, PetscInt *dimensions[])
3012: {
3013: PetscFunctionBegin;
3015: PetscCall(PetscDSSetUp(prob));
3017: *dimensions = prob->Nb;
3018: PetscFunctionReturn(PETSC_SUCCESS);
3019: }
3021: /*@
3022: PetscDSGetComponents - Returns the number of components for each field on an evaluation point
3024: Not Collective
3026: Input Parameter:
3027: . prob - The `PetscDS` object
3029: Output Parameter:
3030: . components - The number of components
3032: Level: beginner
3034: .seealso: `PetscDS`, `PetscDSGetComponentOffsets()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
3035: @*/
3036: PetscErrorCode PetscDSGetComponents(PetscDS prob, PetscInt *components[])
3037: {
3038: PetscFunctionBegin;
3040: PetscCall(PetscDSSetUp(prob));
3042: *components = prob->Nc;
3043: PetscFunctionReturn(PETSC_SUCCESS);
3044: }
3046: /*@
3047: PetscDSGetComponentOffset - Returns the offset of the given field on an evaluation point
3049: Not Collective
3051: Input Parameters:
3052: + prob - The `PetscDS` object
3053: - f - The field number
3055: Output Parameter:
3056: . off - The offset
3058: Level: beginner
3060: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
3061: @*/
3062: PetscErrorCode PetscDSGetComponentOffset(PetscDS prob, PetscInt f, PetscInt *off)
3063: {
3064: PetscFunctionBegin;
3067: 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);
3068: PetscCall(PetscDSSetUp(prob));
3069: *off = prob->off[f];
3070: PetscFunctionReturn(PETSC_SUCCESS);
3071: }
3073: /*@
3074: PetscDSGetComponentOffsets - Returns the offset of each field on an evaluation point
3076: Not Collective
3078: Input Parameter:
3079: . prob - The `PetscDS` object
3081: Output Parameter:
3082: . offsets - The offsets
3084: Level: beginner
3086: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
3087: @*/
3088: PetscErrorCode PetscDSGetComponentOffsets(PetscDS prob, PetscInt *offsets[])
3089: {
3090: PetscFunctionBegin;
3093: PetscCall(PetscDSSetUp(prob));
3094: *offsets = prob->off;
3095: PetscFunctionReturn(PETSC_SUCCESS);
3096: }
3098: /*@
3099: PetscDSGetComponentDerivativeOffsets - Returns the offset of each field derivative on an evaluation point
3101: Not Collective
3103: Input Parameter:
3104: . prob - The `PetscDS` object
3106: Output Parameter:
3107: . offsets - The offsets
3109: Level: beginner
3111: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
3112: @*/
3113: PetscErrorCode PetscDSGetComponentDerivativeOffsets(PetscDS prob, PetscInt *offsets[])
3114: {
3115: PetscFunctionBegin;
3118: PetscCall(PetscDSSetUp(prob));
3119: *offsets = prob->offDer;
3120: PetscFunctionReturn(PETSC_SUCCESS);
3121: }
3123: /*@
3124: PetscDSGetComponentOffsetsCohesive - Returns the offset of each field on an evaluation point
3126: Not Collective
3128: Input Parameters:
3129: + ds - The `PetscDS` object
3130: - s - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive
3132: Output Parameter:
3133: . offsets - The offsets
3135: Level: beginner
3137: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
3138: @*/
3139: PetscErrorCode PetscDSGetComponentOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[])
3140: {
3141: PetscFunctionBegin;
3144: PetscCheck(ds->isCohesive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cohesive offsets are only valid for a cohesive DS");
3145: PetscCheck(!(s < 0) && !(s > 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cohesive side %" PetscInt_FMT " is not in [0, 2]", s);
3146: PetscCall(PetscDSSetUp(ds));
3147: *offsets = ds->offCohesive[s];
3148: PetscFunctionReturn(PETSC_SUCCESS);
3149: }
3151: /*@
3152: PetscDSGetComponentDerivativeOffsetsCohesive - Returns the offset of each field derivative on an evaluation point
3154: Not Collective
3156: Input Parameters:
3157: + ds - The `PetscDS` object
3158: - s - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive
3160: Output Parameter:
3161: . offsets - The offsets
3163: Level: beginner
3165: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
3166: @*/
3167: PetscErrorCode PetscDSGetComponentDerivativeOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[])
3168: {
3169: PetscFunctionBegin;
3172: PetscCheck(ds->isCohesive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cohesive offsets are only valid for a cohesive DS");
3173: PetscCheck(!(s < 0) && !(s > 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cohesive side %" PetscInt_FMT " is not in [0, 2]", s);
3174: PetscCall(PetscDSSetUp(ds));
3175: *offsets = ds->offDerCohesive[s];
3176: PetscFunctionReturn(PETSC_SUCCESS);
3177: }
3179: /*@C
3180: PetscDSGetTabulation - Return the basis tabulation at quadrature points for the volume discretization
3182: Not Collective
3184: Input Parameter:
3185: . prob - The `PetscDS` object
3187: Output Parameter:
3188: . T - The basis function and derivatives tabulation at quadrature points for each field
3190: Level: intermediate
3192: .seealso: `PetscDS`, `PetscTabulation`, `PetscDSCreate()`
3193: @*/
3194: PetscErrorCode PetscDSGetTabulation(PetscDS prob, PetscTabulation *T[])
3195: {
3196: PetscFunctionBegin;
3199: PetscCall(PetscDSSetUp(prob));
3200: *T = prob->T;
3201: PetscFunctionReturn(PETSC_SUCCESS);
3202: }
3204: /*@C
3205: PetscDSGetFaceTabulation - Return the basis tabulation at quadrature points on the faces
3207: Not Collective
3209: Input Parameter:
3210: . prob - The `PetscDS` object
3212: Output Parameter:
3213: . Tf - The basis function and derivative tabulation on each local face at quadrature points for each and field
3215: Level: intermediate
3217: .seealso: `PetscTabulation`, `PetscDS`, `PetscDSGetTabulation()`, `PetscDSCreate()`
3218: @*/
3219: PetscErrorCode PetscDSGetFaceTabulation(PetscDS prob, PetscTabulation *Tf[])
3220: {
3221: PetscFunctionBegin;
3224: PetscCall(PetscDSSetUp(prob));
3225: *Tf = prob->Tf;
3226: PetscFunctionReturn(PETSC_SUCCESS);
3227: }
3229: PetscErrorCode PetscDSGetEvaluationArrays(PetscDS prob, PetscScalar **u, PetscScalar **u_t, PetscScalar **u_x)
3230: {
3231: PetscFunctionBegin;
3233: PetscCall(PetscDSSetUp(prob));
3234: if (u) {
3236: *u = prob->u;
3237: }
3238: if (u_t) {
3240: *u_t = prob->u_t;
3241: }
3242: if (u_x) {
3244: *u_x = prob->u_x;
3245: }
3246: PetscFunctionReturn(PETSC_SUCCESS);
3247: }
3249: PetscErrorCode PetscDSGetWeakFormArrays(PetscDS prob, PetscScalar **f0, PetscScalar **f1, PetscScalar **g0, PetscScalar **g1, PetscScalar **g2, PetscScalar **g3)
3250: {
3251: PetscFunctionBegin;
3253: PetscCall(PetscDSSetUp(prob));
3254: if (f0) {
3256: *f0 = prob->f0;
3257: }
3258: if (f1) {
3260: *f1 = prob->f1;
3261: }
3262: if (g0) {
3264: *g0 = prob->g0;
3265: }
3266: if (g1) {
3268: *g1 = prob->g1;
3269: }
3270: if (g2) {
3272: *g2 = prob->g2;
3273: }
3274: if (g3) {
3276: *g3 = prob->g3;
3277: }
3278: PetscFunctionReturn(PETSC_SUCCESS);
3279: }
3281: PetscErrorCode PetscDSGetWorkspace(PetscDS prob, PetscReal **x, PetscScalar **basisReal, PetscScalar **basisDerReal, PetscScalar **testReal, PetscScalar **testDerReal)
3282: {
3283: PetscFunctionBegin;
3285: PetscCall(PetscDSSetUp(prob));
3286: if (x) {
3288: *x = prob->x;
3289: }
3290: if (basisReal) {
3292: *basisReal = prob->basisReal;
3293: }
3294: if (basisDerReal) {
3296: *basisDerReal = prob->basisDerReal;
3297: }
3298: if (testReal) {
3300: *testReal = prob->testReal;
3301: }
3302: if (testDerReal) {
3304: *testDerReal = prob->testDerReal;
3305: }
3306: PetscFunctionReturn(PETSC_SUCCESS);
3307: }
3309: /*@C
3310: PetscDSAddBoundary - Add a boundary condition to the model. The pointwise functions are used to provide boundary values for essential boundary conditions.
3311: 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
3312: integrals should be performed, using the kernels from `PetscDSSetBdResidual()`.
3314: Collective
3316: Input Parameters:
3317: + ds - The PetscDS object
3318: . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
3319: . name - The BC name
3320: . label - The label defining constrained points
3321: . Nv - The number of `DMLabel` values for constrained points
3322: . values - An array of label values for constrained points
3323: . field - The field to constrain
3324: . Nc - The number of constrained field components (0 will constrain all fields)
3325: . comps - An array of constrained component numbers
3326: . bcFunc - A pointwise function giving boundary values
3327: . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL
3328: - ctx - An optional user context for bcFunc
3330: Output Parameter:
3331: - bd - The boundary number
3333: Options Database Keys:
3334: + -bc_<boundary name> <num> - Overrides the boundary ids
3335: - -bc_<boundary name>_comp <num> - Overrides the boundary components
3337: Level: developer
3339: Note:
3340: Both `bcFunc` and `bcFunc_t` will depend on the boundary condition type. If the type if `DM_BC_ESSENTIAL`, Then the calling sequence is:
3342: $ void bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])
3344: If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, then the calling sequence is:
3345: .vb
3346: void bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
3347: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
3348: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
3349: PetscReal time, const PetscReal x[], PetscScalar bcval[])
3350: .ve
3351: + dim - the spatial dimension
3352: . Nf - the number of fields
3353: . uOff - the offset into u[] and u_t[] for each field
3354: . uOff_x - the offset into u_x[] for each field
3355: . u - each field evaluated at the current point
3356: . u_t - the time derivative of each field evaluated at the current point
3357: . u_x - the gradient of each field evaluated at the current point
3358: . aOff - the offset into a[] and a_t[] for each auxiliary field
3359: . aOff_x - the offset into a_x[] for each auxiliary field
3360: . a - each auxiliary field evaluated at the current point
3361: . a_t - the time derivative of each auxiliary field evaluated at the current point
3362: . a_x - the gradient of auxiliary each field evaluated at the current point
3363: . t - current time
3364: . x - coordinates of the current point
3365: . numConstants - number of constant parameters
3366: . constants - constant parameters
3367: - bcval - output values at the current point
3369: .seealso: `PetscDS`, `PetscWeakForm`, `DMLabel`, `DMBoundaryConditionType`, `PetscDSAddBoundaryByName()`, `PetscDSGetBoundary()`, `PetscDSSetResidual()`, `PetscDSSetBdResidual()`
3370: @*/
3371: 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)
3372: {
3373: DSBoundary head = ds->boundary, b;
3374: PetscInt n = 0;
3375: const char *lname;
3377: PetscFunctionBegin;
3385: 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);
3386: if (Nc > 0) {
3387: PetscInt *fcomps;
3388: PetscInt c;
3390: PetscCall(PetscDSGetComponents(ds, &fcomps));
3391: 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);
3392: for (c = 0; c < Nc; ++c) {
3393: 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);
3394: }
3395: }
3396: PetscCall(PetscNew(&b));
3397: PetscCall(PetscStrallocpy(name, (char **)&b->name));
3398: PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf));
3399: PetscCall(PetscWeakFormSetNumFields(b->wf, ds->Nf));
3400: PetscCall(PetscMalloc1(Nv, &b->values));
3401: if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv));
3402: PetscCall(PetscMalloc1(Nc, &b->comps));
3403: if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc));
3404: PetscCall(PetscObjectGetName((PetscObject)label, &lname));
3405: PetscCall(PetscStrallocpy(lname, (char **)&b->lname));
3406: b->type = type;
3407: b->label = label;
3408: b->Nv = Nv;
3409: b->field = field;
3410: b->Nc = Nc;
3411: b->func = bcFunc;
3412: b->func_t = bcFunc_t;
3413: b->ctx = ctx;
3414: b->next = NULL;
3415: /* Append to linked list so that we can preserve the order */
3416: if (!head) ds->boundary = b;
3417: while (head) {
3418: if (!head->next) {
3419: head->next = b;
3420: head = b;
3421: }
3422: head = head->next;
3423: ++n;
3424: }
3425: if (bd) {
3427: *bd = n;
3428: }
3429: PetscFunctionReturn(PETSC_SUCCESS);
3430: }
3432: /*@C
3433: PetscDSAddBoundaryByName - Add a boundary condition to the model. The pointwise functions are used to provide boundary values for essential boundary conditions.
3434: In FEM, they are acting upon by dual basis functionals to generate FEM coefficients which are fixed. Natural boundary conditions signal to PETSc that
3435: boundary integrals should be performed, using the kernels from `PetscDSSetBdResidual()`.
3437: Collective
3439: Input Parameters:
3440: + ds - The `PetscDS` object
3441: . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
3442: . name - The BC name
3443: . lname - The naem of the label defining constrained points
3444: . Nv - The number of `DMLabel` values for constrained points
3445: . values - An array of label values for constrained points
3446: . field - The field to constrain
3447: . Nc - The number of constrained field components (0 will constrain all fields)
3448: . comps - An array of constrained component numbers
3449: . bcFunc - A pointwise function giving boundary values
3450: . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL
3451: - ctx - An optional user context for bcFunc
3453: Output Parameter:
3454: - bd - The boundary number
3456: Options Database Keys:
3457: + -bc_<boundary name> <num> - Overrides the boundary ids
3458: - -bc_<boundary name>_comp <num> - Overrides the boundary components
3460: Calling Sequence of `bcFunc` and `bcFunc_t`:
3461: If the type is `DM_BC_ESSENTIAL`
3462: .vb
3463: void bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])
3464: .ve
3465: If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value,
3466: .vb
3467: void bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
3468: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
3469: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
3470: PetscReal time, const PetscReal x[], PetscScalar bcval[])
3471: .ve
3472: + dim - the spatial dimension
3473: . Nf - the number of fields
3474: . uOff - the offset into u[] and u_t[] for each field
3475: . uOff_x - the offset into u_x[] for each field
3476: . u - each field evaluated at the current point
3477: . u_t - the time derivative of each field evaluated at the current point
3478: . u_x - the gradient of each field evaluated at the current point
3479: . aOff - the offset into a[] and a_t[] for each auxiliary field
3480: . aOff_x - the offset into a_x[] for each auxiliary field
3481: . a - each auxiliary field evaluated at the current point
3482: . a_t - the time derivative of each auxiliary field evaluated at the current point
3483: . a_x - the gradient of auxiliary each field evaluated at the current point
3484: . t - current time
3485: . x - coordinates of the current point
3486: . numConstants - number of constant parameters
3487: . constants - constant parameters
3488: - bcval - output values at the current point
3490: Level: developer
3492: Note:
3493: This function should only be used with `DMFOREST` currently, since labels cannot be defined before the underlying `DMPLEX` is built.
3495: .seealso: `PetscDS`, `PetscWeakForm`, `DMLabel`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSSetResidual()`, `PetscDSSetBdResidual()`
3496: @*/
3497: 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)
3498: {
3499: DSBoundary head = ds->boundary, b;
3500: PetscInt n = 0;
3502: PetscFunctionBegin;
3510: PetscCall(PetscNew(&b));
3511: PetscCall(PetscStrallocpy(name, (char **)&b->name));
3512: PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf));
3513: PetscCall(PetscWeakFormSetNumFields(b->wf, ds->Nf));
3514: PetscCall(PetscMalloc1(Nv, &b->values));
3515: if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv));
3516: PetscCall(PetscMalloc1(Nc, &b->comps));
3517: if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc));
3518: PetscCall(PetscStrallocpy(lname, (char **)&b->lname));
3519: b->type = type;
3520: b->label = NULL;
3521: b->Nv = Nv;
3522: b->field = field;
3523: b->Nc = Nc;
3524: b->func = bcFunc;
3525: b->func_t = bcFunc_t;
3526: b->ctx = ctx;
3527: b->next = NULL;
3528: /* Append to linked list so that we can preserve the order */
3529: if (!head) ds->boundary = b;
3530: while (head) {
3531: if (!head->next) {
3532: head->next = b;
3533: head = b;
3534: }
3535: head = head->next;
3536: ++n;
3537: }
3538: if (bd) {
3540: *bd = n;
3541: }
3542: PetscFunctionReturn(PETSC_SUCCESS);
3543: }
3545: /*@C
3546: PetscDSUpdateBoundary - Change a boundary condition for the model. The pointwise functions are used to provide boundary values for essential boundary conditions.
3547: 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
3548: should be performed, using the kernels from `PetscDSSetBdResidual()`.
3550: Input Parameters:
3551: + ds - The `PetscDS` object
3552: . bd - The boundary condition number
3553: . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
3554: . name - The BC name
3555: . label - The label defining constrained points
3556: . Nv - The number of `DMLabel` ids for constrained points
3557: . values - An array of ids for constrained points
3558: . field - The field to constrain
3559: . Nc - The number of constrained field components
3560: . comps - An array of constrained component numbers
3561: . bcFunc - A pointwise function giving boundary values
3562: . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL
3563: - ctx - An optional user context for bcFunc
3565: Level: developer
3567: Note:
3568: The boundary condition number is the order in which it was registered. The user can get the number of boundary conditions from `PetscDSGetNumBoundary()`.
3569: See `PetscDSAddBoundary()` for a description of the calling sequences for the callbacks.
3571: .seealso: `PetscDS`, `PetscWeakForm`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSGetNumBoundary()`, `DMLabel`
3572: @*/
3573: 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)
3574: {
3575: DSBoundary b = ds->boundary;
3576: PetscInt n = 0;
3578: PetscFunctionBegin;
3580: while (b) {
3581: if (n == bd) break;
3582: b = b->next;
3583: ++n;
3584: }
3585: PetscCheck(b, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bd, n);
3586: if (name) {
3587: PetscCall(PetscFree(b->name));
3588: PetscCall(PetscStrallocpy(name, (char **)&b->name));
3589: }
3590: b->type = type;
3591: if (label) {
3592: const char *name;
3594: b->label = label;
3595: PetscCall(PetscFree(b->lname));
3596: PetscCall(PetscObjectGetName((PetscObject)label, &name));
3597: PetscCall(PetscStrallocpy(name, (char **)&b->lname));
3598: }
3599: if (Nv >= 0) {
3600: b->Nv = Nv;
3601: PetscCall(PetscFree(b->values));
3602: PetscCall(PetscMalloc1(Nv, &b->values));
3603: if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv));
3604: }
3605: if (field >= 0) b->field = field;
3606: if (Nc >= 0) {
3607: b->Nc = Nc;
3608: PetscCall(PetscFree(b->comps));
3609: PetscCall(PetscMalloc1(Nc, &b->comps));
3610: if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc));
3611: }
3612: if (bcFunc) b->func = bcFunc;
3613: if (bcFunc_t) b->func_t = bcFunc_t;
3614: if (ctx) b->ctx = ctx;
3615: PetscFunctionReturn(PETSC_SUCCESS);
3616: }
3618: /*@
3619: PetscDSGetNumBoundary - Get the number of registered BC
3621: Input Parameter:
3622: . ds - The `PetscDS` object
3624: Output Parameter:
3625: . numBd - The number of BC
3627: Level: intermediate
3629: .seealso: `PetscDS`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`
3630: @*/
3631: PetscErrorCode PetscDSGetNumBoundary(PetscDS ds, PetscInt *numBd)
3632: {
3633: DSBoundary b = ds->boundary;
3635: PetscFunctionBegin;
3638: *numBd = 0;
3639: while (b) {
3640: ++(*numBd);
3641: b = b->next;
3642: }
3643: PetscFunctionReturn(PETSC_SUCCESS);
3644: }
3646: /*@C
3647: PetscDSGetBoundary - Gets a boundary condition to the model
3649: Input Parameters:
3650: + ds - The `PetscDS` object
3651: - bd - The BC number
3653: Output Parameters:
3654: + wf - The `PetscWeakForm` holding the pointwise functions
3655: . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
3656: . name - The BC name
3657: . label - The label defining constrained points
3658: . Nv - The number of `DMLabel` ids for constrained points
3659: . values - An array of ids for constrained points
3660: . field - The field to constrain
3661: . Nc - The number of constrained field components
3662: . comps - An array of constrained component numbers
3663: . bcFunc - A pointwise function giving boundary values
3664: . bcFunc_t - A pointwise function giving the time derivative of the boundary values
3665: - ctx - An optional user context for bcFunc
3667: Options Database Keys:
3668: + -bc_<boundary name> <num> - Overrides the boundary ids
3669: - -bc_<boundary name>_comp <num> - Overrides the boundary components
3671: Level: developer
3673: .seealso: `PetscDS`, `PetscWeakForm`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `DMLabel`
3674: @*/
3675: 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)
3676: {
3677: DSBoundary b = ds->boundary;
3678: PetscInt n = 0;
3680: PetscFunctionBegin;
3682: while (b) {
3683: if (n == bd) break;
3684: b = b->next;
3685: ++n;
3686: }
3687: PetscCheck(b, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bd, n);
3688: if (wf) {
3690: *wf = b->wf;
3691: }
3692: if (type) {
3694: *type = b->type;
3695: }
3696: if (name) {
3698: *name = b->name;
3699: }
3700: if (label) {
3702: *label = b->label;
3703: }
3704: if (Nv) {
3706: *Nv = b->Nv;
3707: }
3708: if (values) {
3710: *values = b->values;
3711: }
3712: if (field) {
3714: *field = b->field;
3715: }
3716: if (Nc) {
3718: *Nc = b->Nc;
3719: }
3720: if (comps) {
3722: *comps = b->comps;
3723: }
3724: if (func) {
3726: *func = b->func;
3727: }
3728: if (func_t) {
3730: *func_t = b->func_t;
3731: }
3732: if (ctx) {
3734: *ctx = b->ctx;
3735: }
3736: PetscFunctionReturn(PETSC_SUCCESS);
3737: }
3739: static PetscErrorCode DSBoundaryDuplicate_Internal(DSBoundary b, DSBoundary *bNew)
3740: {
3741: PetscFunctionBegin;
3742: PetscCall(PetscNew(bNew));
3743: PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &(*bNew)->wf));
3744: PetscCall(PetscWeakFormCopy(b->wf, (*bNew)->wf));
3745: PetscCall(PetscStrallocpy(b->name, (char **)&((*bNew)->name)));
3746: PetscCall(PetscStrallocpy(b->lname, (char **)&((*bNew)->lname)));
3747: (*bNew)->type = b->type;
3748: (*bNew)->label = b->label;
3749: (*bNew)->Nv = b->Nv;
3750: PetscCall(PetscMalloc1(b->Nv, &(*bNew)->values));
3751: PetscCall(PetscArraycpy((*bNew)->values, b->values, b->Nv));
3752: (*bNew)->field = b->field;
3753: (*bNew)->Nc = b->Nc;
3754: PetscCall(PetscMalloc1(b->Nc, &(*bNew)->comps));
3755: PetscCall(PetscArraycpy((*bNew)->comps, b->comps, b->Nc));
3756: (*bNew)->func = b->func;
3757: (*bNew)->func_t = b->func_t;
3758: (*bNew)->ctx = b->ctx;
3759: PetscFunctionReturn(PETSC_SUCCESS);
3760: }
3762: /*@
3763: PetscDSCopyBoundary - Copy all boundary condition objects to the new problem
3765: Not Collective
3767: Input Parameters:
3768: + ds - The source `PetscDS` object
3769: . numFields - The number of selected fields, or `PETSC_DEFAULT` for all fields
3770: - fields - The selected fields, or NULL for all fields
3772: Output Parameter:
3773: . newds - The target `PetscDS`, now with a copy of the boundary conditions
3775: Level: intermediate
3777: .seealso: `PetscDS`, `DMBoundary`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3778: @*/
3779: PetscErrorCode PetscDSCopyBoundary(PetscDS ds, PetscInt numFields, const PetscInt fields[], PetscDS newds)
3780: {
3781: DSBoundary b, *lastnext;
3783: PetscFunctionBegin;
3786: if (ds == newds) PetscFunctionReturn(PETSC_SUCCESS);
3787: PetscCall(PetscDSDestroyBoundary(newds));
3788: lastnext = &(newds->boundary);
3789: for (b = ds->boundary; b; b = b->next) {
3790: DSBoundary bNew;
3791: PetscInt fieldNew = -1;
3793: if (numFields > 0 && fields) {
3794: PetscInt f;
3796: for (f = 0; f < numFields; ++f)
3797: if (b->field == fields[f]) break;
3798: if (f == numFields) continue;
3799: fieldNew = f;
3800: }
3801: PetscCall(DSBoundaryDuplicate_Internal(b, &bNew));
3802: bNew->field = fieldNew < 0 ? b->field : fieldNew;
3803: *lastnext = bNew;
3804: lastnext = &(bNew->next);
3805: }
3806: PetscFunctionReturn(PETSC_SUCCESS);
3807: }
3809: /*@
3810: PetscDSDestroyBoundary - Remove all `DMBoundary` objects from the `PetscDS`
3812: Not Collective
3814: Input Parameter:
3815: . ds - The `PetscDS` object
3817: Level: intermediate
3819: .seealso: `PetscDS`, `DMBoundary`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`
3820: @*/
3821: PetscErrorCode PetscDSDestroyBoundary(PetscDS ds)
3822: {
3823: DSBoundary next = ds->boundary;
3825: PetscFunctionBegin;
3826: while (next) {
3827: DSBoundary b = next;
3829: next = b->next;
3830: PetscCall(PetscWeakFormDestroy(&b->wf));
3831: PetscCall(PetscFree(b->name));
3832: PetscCall(PetscFree(b->lname));
3833: PetscCall(PetscFree(b->values));
3834: PetscCall(PetscFree(b->comps));
3835: PetscCall(PetscFree(b));
3836: }
3837: PetscFunctionReturn(PETSC_SUCCESS);
3838: }
3840: /*@
3841: PetscDSSelectDiscretizations - Copy discretizations to the new problem with different field layout
3843: Not Collective
3845: Input Parameters:
3846: + prob - The `PetscDS` object
3847: . numFields - Number of new fields
3848: - fields - Old field number for each new field
3850: Output Parameter:
3851: . newprob - The `PetscDS` copy
3853: Level: intermediate
3855: .seealso: `PetscDS`, `PetscDSSelectEquations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3856: @*/
3857: PetscErrorCode PetscDSSelectDiscretizations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob)
3858: {
3859: PetscInt Nf, Nfn, fn;
3861: PetscFunctionBegin;
3865: PetscCall(PetscDSGetNumFields(prob, &Nf));
3866: PetscCall(PetscDSGetNumFields(newprob, &Nfn));
3867: numFields = numFields < 0 ? Nf : numFields;
3868: for (fn = 0; fn < numFields; ++fn) {
3869: const PetscInt f = fields ? fields[fn] : fn;
3870: PetscObject disc;
3872: if (f >= Nf) continue;
3873: PetscCall(PetscDSGetDiscretization(prob, f, &disc));
3874: PetscCall(PetscDSSetDiscretization(newprob, fn, disc));
3875: }
3876: PetscFunctionReturn(PETSC_SUCCESS);
3877: }
3879: /*@
3880: PetscDSSelectEquations - Copy pointwise function pointers to the new problem with different field layout
3882: Not Collective
3884: Input Parameters:
3885: + prob - The `PetscDS` object
3886: . numFields - Number of new fields
3887: - fields - Old field number for each new field
3889: Output Parameter:
3890: . newprob - The `PetscDS` copy
3892: Level: intermediate
3894: .seealso: `PetscDS`, `PetscDSSelectDiscretizations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3895: @*/
3896: PetscErrorCode PetscDSSelectEquations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob)
3897: {
3898: PetscInt Nf, Nfn, fn, gn;
3900: PetscFunctionBegin;
3904: PetscCall(PetscDSGetNumFields(prob, &Nf));
3905: PetscCall(PetscDSGetNumFields(newprob, &Nfn));
3906: 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);
3907: for (fn = 0; fn < numFields; ++fn) {
3908: const PetscInt f = fields ? fields[fn] : fn;
3909: PetscPointFunc obj;
3910: PetscPointFunc f0, f1;
3911: PetscBdPointFunc f0Bd, f1Bd;
3912: PetscRiemannFunc r;
3914: if (f >= Nf) continue;
3915: PetscCall(PetscDSGetObjective(prob, f, &obj));
3916: PetscCall(PetscDSGetResidual(prob, f, &f0, &f1));
3917: PetscCall(PetscDSGetBdResidual(prob, f, &f0Bd, &f1Bd));
3918: PetscCall(PetscDSGetRiemannSolver(prob, f, &r));
3919: PetscCall(PetscDSSetObjective(newprob, fn, obj));
3920: PetscCall(PetscDSSetResidual(newprob, fn, f0, f1));
3921: PetscCall(PetscDSSetBdResidual(newprob, fn, f0Bd, f1Bd));
3922: PetscCall(PetscDSSetRiemannSolver(newprob, fn, r));
3923: for (gn = 0; gn < numFields; ++gn) {
3924: const PetscInt g = fields ? fields[gn] : gn;
3925: PetscPointJac g0, g1, g2, g3;
3926: PetscPointJac g0p, g1p, g2p, g3p;
3927: PetscBdPointJac g0Bd, g1Bd, g2Bd, g3Bd;
3929: if (g >= Nf) continue;
3930: PetscCall(PetscDSGetJacobian(prob, f, g, &g0, &g1, &g2, &g3));
3931: PetscCall(PetscDSGetJacobianPreconditioner(prob, f, g, &g0p, &g1p, &g2p, &g3p));
3932: PetscCall(PetscDSGetBdJacobian(prob, f, g, &g0Bd, &g1Bd, &g2Bd, &g3Bd));
3933: PetscCall(PetscDSSetJacobian(newprob, fn, gn, g0, g1, g2, g3));
3934: PetscCall(PetscDSSetJacobianPreconditioner(newprob, fn, gn, g0p, g1p, g2p, g3p));
3935: PetscCall(PetscDSSetBdJacobian(newprob, fn, gn, g0Bd, g1Bd, g2Bd, g3Bd));
3936: }
3937: }
3938: PetscFunctionReturn(PETSC_SUCCESS);
3939: }
3941: /*@
3942: PetscDSCopyEquations - Copy all pointwise function pointers to another `PetscDS`
3944: Not Collective
3946: Input Parameter:
3947: . prob - The `PetscDS` object
3949: Output Parameter:
3950: . newprob - The `PetscDS` copy
3952: Level: intermediate
3954: .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3955: @*/
3956: PetscErrorCode PetscDSCopyEquations(PetscDS prob, PetscDS newprob)
3957: {
3958: PetscWeakForm wf, newwf;
3959: PetscInt Nf, Ng;
3961: PetscFunctionBegin;
3964: PetscCall(PetscDSGetNumFields(prob, &Nf));
3965: PetscCall(PetscDSGetNumFields(newprob, &Ng));
3966: PetscCheck(Nf == Ng, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_SIZ, "Number of fields must match %" PetscInt_FMT " != %" PetscInt_FMT, Nf, Ng);
3967: PetscCall(PetscDSGetWeakForm(prob, &wf));
3968: PetscCall(PetscDSGetWeakForm(newprob, &newwf));
3969: PetscCall(PetscWeakFormCopy(wf, newwf));
3970: PetscFunctionReturn(PETSC_SUCCESS);
3971: }
3973: /*@
3974: PetscDSCopyConstants - Copy all constants to another `PetscDS`
3976: Not Collective
3978: Input Parameter:
3979: . prob - The `PetscDS` object
3981: Output Parameter:
3982: . newprob - The `PetscDS` copy
3984: Level: intermediate
3986: .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3987: @*/
3988: PetscErrorCode PetscDSCopyConstants(PetscDS prob, PetscDS newprob)
3989: {
3990: PetscInt Nc;
3991: const PetscScalar *constants;
3993: PetscFunctionBegin;
3996: PetscCall(PetscDSGetConstants(prob, &Nc, &constants));
3997: PetscCall(PetscDSSetConstants(newprob, Nc, (PetscScalar *)constants));
3998: PetscFunctionReturn(PETSC_SUCCESS);
3999: }
4001: /*@
4002: PetscDSCopyExactSolutions - Copy all exact solutions to another `PetscDS`
4004: Not Collective
4006: Input Parameter:
4007: . ds - The `PetscDS` object
4009: Output Parameter:
4010: . newds - The `PetscDS` copy
4012: Level: intermediate
4014: .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
4015: @*/
4016: PetscErrorCode PetscDSCopyExactSolutions(PetscDS ds, PetscDS newds)
4017: {
4018: PetscSimplePointFunc sol;
4019: void *ctx;
4020: PetscInt Nf, f;
4022: PetscFunctionBegin;
4025: PetscCall(PetscDSGetNumFields(ds, &Nf));
4026: for (f = 0; f < Nf; ++f) {
4027: PetscCall(PetscDSGetExactSolution(ds, f, &sol, &ctx));
4028: PetscCall(PetscDSSetExactSolution(newds, f, sol, ctx));
4029: PetscCall(PetscDSGetExactSolutionTimeDerivative(ds, f, &sol, &ctx));
4030: PetscCall(PetscDSSetExactSolutionTimeDerivative(newds, f, sol, ctx));
4031: }
4032: PetscFunctionReturn(PETSC_SUCCESS);
4033: }
4035: PetscErrorCode PetscDSCopy(PetscDS ds, DM dmNew, PetscDS dsNew)
4036: {
4037: DSBoundary b;
4038: PetscInt cdim, Nf, f, d;
4039: PetscBool isCohesive;
4040: void *ctx;
4042: PetscFunctionBegin;
4043: PetscCall(PetscDSCopyConstants(ds, dsNew));
4044: PetscCall(PetscDSCopyExactSolutions(ds, dsNew));
4045: PetscCall(PetscDSSelectDiscretizations(ds, PETSC_DETERMINE, NULL, dsNew));
4046: PetscCall(PetscDSCopyEquations(ds, dsNew));
4047: PetscCall(PetscDSGetNumFields(ds, &Nf));
4048: for (f = 0; f < Nf; ++f) {
4049: PetscCall(PetscDSGetContext(ds, f, &ctx));
4050: PetscCall(PetscDSSetContext(dsNew, f, ctx));
4051: PetscCall(PetscDSGetCohesive(ds, f, &isCohesive));
4052: PetscCall(PetscDSSetCohesive(dsNew, f, isCohesive));
4053: PetscCall(PetscDSGetJetDegree(ds, f, &d));
4054: PetscCall(PetscDSSetJetDegree(dsNew, f, d));
4055: }
4056: if (Nf) {
4057: PetscCall(PetscDSGetCoordinateDimension(ds, &cdim));
4058: PetscCall(PetscDSSetCoordinateDimension(dsNew, cdim));
4059: }
4060: PetscCall(PetscDSCopyBoundary(ds, PETSC_DETERMINE, NULL, dsNew));
4061: for (b = dsNew->boundary; b; b = b->next) {
4062: PetscCall(DMGetLabel(dmNew, b->lname, &b->label));
4063: /* Do not check if label exists here, since p4est calls this for the reference tree which does not have the labels */
4064: //PetscCheck(b->label,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s missing in new DM", name);
4065: }
4066: PetscFunctionReturn(PETSC_SUCCESS);
4067: }
4069: PetscErrorCode PetscDSGetHeightSubspace(PetscDS prob, PetscInt height, PetscDS *subprob)
4070: {
4071: PetscInt dim, Nf, f;
4073: PetscFunctionBegin;
4076: if (height == 0) {
4077: *subprob = prob;
4078: PetscFunctionReturn(PETSC_SUCCESS);
4079: }
4080: PetscCall(PetscDSGetNumFields(prob, &Nf));
4081: PetscCall(PetscDSGetSpatialDimension(prob, &dim));
4082: PetscCheck(height <= dim, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_OUTOFRANGE, "DS can only handle height in [0, %" PetscInt_FMT "], not %" PetscInt_FMT, dim, height);
4083: if (!prob->subprobs) PetscCall(PetscCalloc1(dim, &prob->subprobs));
4084: if (!prob->subprobs[height - 1]) {
4085: PetscInt cdim;
4087: PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)prob), &prob->subprobs[height - 1]));
4088: PetscCall(PetscDSGetCoordinateDimension(prob, &cdim));
4089: PetscCall(PetscDSSetCoordinateDimension(prob->subprobs[height - 1], cdim));
4090: for (f = 0; f < Nf; ++f) {
4091: PetscFE subfe;
4092: PetscObject obj;
4093: PetscClassId id;
4095: PetscCall(PetscDSGetDiscretization(prob, f, &obj));
4096: PetscCall(PetscObjectGetClassId(obj, &id));
4097: if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetHeightSubspace((PetscFE)obj, height, &subfe));
4098: else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unsupported discretization type for field %" PetscInt_FMT, f);
4099: PetscCall(PetscDSSetDiscretization(prob->subprobs[height - 1], f, (PetscObject)subfe));
4100: }
4101: }
4102: *subprob = prob->subprobs[height - 1];
4103: PetscFunctionReturn(PETSC_SUCCESS);
4104: }
4106: PetscErrorCode PetscDSPermuteQuadPoint(PetscDS ds, PetscInt ornt, PetscInt field, PetscInt q, PetscInt *qperm)
4107: {
4108: IS permIS;
4109: PetscQuadrature quad;
4110: DMPolytopeType ct;
4111: const PetscInt *perm;
4112: PetscInt Na, Nq;
4114: PetscFunctionBeginHot;
4115: PetscCall(PetscFEGetQuadrature((PetscFE)ds->disc[field], &quad));
4116: PetscCall(PetscQuadratureGetData(quad, NULL, NULL, &Nq, NULL, NULL));
4117: PetscCall(PetscQuadratureGetCellType(quad, &ct));
4118: PetscCheck(q >= 0 && q < Nq, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Quadrature point %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", q, Nq);
4119: Na = DMPolytopeTypeGetNumArrangments(ct) / 2;
4120: PetscCheck(ornt >= -Na && ornt < Na, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Orientation %" PetscInt_FMT " of %s is not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", ornt, DMPolytopeTypes[ct], -Na, Na);
4121: if (!ds->quadPerm[(PetscInt)ct]) PetscCall(PetscQuadratureComputePermutations(quad, NULL, &ds->quadPerm[(PetscInt)ct]));
4122: permIS = ds->quadPerm[(PetscInt)ct][ornt + Na];
4123: PetscCall(ISGetIndices(permIS, &perm));
4124: *qperm = perm[q];
4125: PetscCall(ISRestoreIndices(permIS, &perm));
4126: PetscFunctionReturn(PETSC_SUCCESS);
4127: }
4129: PetscErrorCode PetscDSGetDiscType_Internal(PetscDS ds, PetscInt f, PetscDiscType *disctype)
4130: {
4131: PetscObject obj;
4132: PetscClassId id;
4133: PetscInt Nf;
4135: PetscFunctionBegin;
4138: *disctype = PETSC_DISC_NONE;
4139: PetscCall(PetscDSGetNumFields(ds, &Nf));
4140: PetscCheck(f < Nf, PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_SIZ, "Field %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf);
4141: PetscCall(PetscDSGetDiscretization(ds, f, &obj));
4142: if (obj) {
4143: PetscCall(PetscObjectGetClassId(obj, &id));
4144: if (id == PETSCFE_CLASSID) *disctype = PETSC_DISC_FE;
4145: else *disctype = PETSC_DISC_FV;
4146: }
4147: PetscFunctionReturn(PETSC_SUCCESS);
4148: }
4150: static PetscErrorCode PetscDSDestroy_Basic(PetscDS ds)
4151: {
4152: PetscFunctionBegin;
4153: PetscCall(PetscFree(ds->data));
4154: PetscFunctionReturn(PETSC_SUCCESS);
4155: }
4157: static PetscErrorCode PetscDSInitialize_Basic(PetscDS ds)
4158: {
4159: PetscFunctionBegin;
4160: ds->ops->setfromoptions = NULL;
4161: ds->ops->setup = NULL;
4162: ds->ops->view = NULL;
4163: ds->ops->destroy = PetscDSDestroy_Basic;
4164: PetscFunctionReturn(PETSC_SUCCESS);
4165: }
4167: /*MC
4168: PETSCDSBASIC = "basic" - A discrete system with pointwise residual and boundary residual functions
4170: Level: intermediate
4172: .seealso: `PetscDSType`, `PetscDSCreate()`, `PetscDSSetType()`
4173: M*/
4175: PETSC_EXTERN PetscErrorCode PetscDSCreate_Basic(PetscDS ds)
4176: {
4177: PetscDS_Basic *b;
4179: PetscFunctionBegin;
4181: PetscCall(PetscNew(&b));
4182: ds->data = b;
4184: PetscCall(PetscDSInitialize_Basic(ds));
4185: PetscFunctionReturn(PETSC_SUCCESS);
4186: }