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: /*@C
9: PetscDSRegister - Adds a new `PetscDS` implementation
11: Not Collective; No Fortran Support
13: Input Parameters:
14: + sname - The name of a new user-defined creation routine
15: - function - The creation routine itself
17: Example Usage:
18: .vb
19: PetscDSRegister("my_ds", MyPetscDSCreate);
20: .ve
22: Then, your PetscDS type can be chosen with the procedural interface via
23: .vb
24: PetscDSCreate(MPI_Comm, PetscDS *);
25: PetscDSSetType(PetscDS, "my_ds");
26: .ve
27: or at runtime via the option
28: .vb
29: -petscds_type my_ds
30: .ve
32: Level: advanced
34: Note:
35: `PetscDSRegister()` may be called multiple times to add several user-defined `PetscDSs`
37: .seealso: `PetscDSType`, `PetscDS`, `PetscDSRegisterAll()`, `PetscDSRegisterDestroy()`
38: @*/
39: PetscErrorCode PetscDSRegister(const char sname[], PetscErrorCode (*function)(PetscDS))
40: {
41: PetscFunctionBegin;
42: PetscCall(PetscFunctionListAdd(&PetscDSList, sname, function));
43: PetscFunctionReturn(PETSC_SUCCESS);
44: }
46: /*@
47: PetscDSSetType - Builds a particular `PetscDS`
49: Collective; No Fortran Support
51: Input Parameters:
52: + prob - The `PetscDS` object
53: - name - The `PetscDSType`
55: Options Database Key:
56: . -petscds_type type - Sets the PetscDS type; use -help for a list of available types
58: Level: intermediate
60: .seealso: `PetscDSType`, `PetscDS`, `PetscDSGetType()`, `PetscDSCreate()`
61: @*/
62: PetscErrorCode PetscDSSetType(PetscDS prob, PetscDSType name)
63: {
64: PetscErrorCode (*r)(PetscDS);
65: PetscBool match;
67: PetscFunctionBegin;
69: PetscCall(PetscObjectTypeCompare((PetscObject)prob, name, &match));
70: if (match) PetscFunctionReturn(PETSC_SUCCESS);
72: PetscCall(PetscDSRegisterAll());
73: PetscCall(PetscFunctionListFind(PetscDSList, name, &r));
74: PetscCheck(r, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDS type: %s", name);
76: PetscTryTypeMethod(prob, destroy);
77: prob->ops->destroy = NULL;
79: PetscCall((*r)(prob));
80: PetscCall(PetscObjectChangeTypeName((PetscObject)prob, name));
81: PetscFunctionReturn(PETSC_SUCCESS);
82: }
84: /*@
85: PetscDSGetType - Gets the `PetscDSType` name (as a string) from the `PetscDS`
87: Not Collective; No Fortran Support
89: Input Parameter:
90: . prob - The `PetscDS`
92: Output Parameter:
93: . name - The `PetscDSType` name
95: Level: intermediate
97: .seealso: `PetscDSType`, `PetscDS`, `PetscDSSetType()`, `PetscDSCreate()`
98: @*/
99: PetscErrorCode PetscDSGetType(PetscDS prob, PetscDSType *name)
100: {
101: PetscFunctionBegin;
103: PetscAssertPointer(name, 2);
104: PetscCall(PetscDSRegisterAll());
105: *name = ((PetscObject)prob)->type_name;
106: PetscFunctionReturn(PETSC_SUCCESS);
107: }
109: static PetscErrorCode PetscDSView_Ascii(PetscDS ds, PetscViewer viewer)
110: {
111: PetscViewerFormat format;
112: const PetscScalar *constants;
113: PetscInt Nf, numConstants, f;
115: PetscFunctionBegin;
116: PetscCall(PetscDSGetNumFields(ds, &Nf));
117: PetscCall(PetscViewerGetFormat(viewer, &format));
118: PetscCall(PetscViewerASCIIPrintf(viewer, "Discrete System with %" PetscInt_FMT " fields\n", Nf));
119: PetscCall(PetscViewerASCIIPushTab(viewer));
120: PetscCall(PetscViewerASCIIPrintf(viewer, " cell total dim %" PetscInt_FMT " total comp %" PetscInt_FMT "\n", ds->totDim, ds->totComp));
121: if (ds->isCohesive) PetscCall(PetscViewerASCIIPrintf(viewer, " cohesive cell\n"));
122: for (f = 0; f < Nf; ++f) {
123: DSBoundary b;
124: PetscObject obj;
125: PetscClassId id;
126: PetscQuadrature q;
127: const char *name;
128: PetscInt Nc, Nq, Nqc;
130: PetscCall(PetscDSGetDiscretization(ds, f, &obj));
131: PetscCall(PetscObjectGetClassId(obj, &id));
132: PetscCall(PetscObjectGetName(obj, &name));
133: PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s", name ? name : "<unknown>"));
134: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
135: if (id == PETSCFE_CLASSID) {
136: PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc));
137: PetscCall(PetscFEGetQuadrature((PetscFE)obj, &q));
138: PetscCall(PetscViewerASCIIPrintf(viewer, " FEM"));
139: } else if (id == PETSCFV_CLASSID) {
140: PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc));
141: PetscCall(PetscFVGetQuadrature((PetscFV)obj, &q));
142: PetscCall(PetscViewerASCIIPrintf(viewer, " FVM"));
143: } else SETERRQ(PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, f);
144: if (Nc > 1) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " components", Nc));
145: else PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " component ", Nc));
146: if (ds->implicit[f]) PetscCall(PetscViewerASCIIPrintf(viewer, " (implicit)"));
147: else PetscCall(PetscViewerASCIIPrintf(viewer, " (explicit)"));
148: if (q) {
149: PetscCall(PetscQuadratureGetData(q, NULL, &Nqc, &Nq, NULL, NULL));
150: PetscCall(PetscViewerASCIIPrintf(viewer, " (Nq %" PetscInt_FMT " Nqc %" PetscInt_FMT ")", Nq, Nqc));
151: }
152: PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "-jet", ds->jetDegree[f]));
153: PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
154: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
155: PetscCall(PetscViewerASCIIPushTab(viewer));
156: if (id == PETSCFE_CLASSID) PetscCall(PetscFEView((PetscFE)obj, viewer));
157: else if (id == PETSCFV_CLASSID) PetscCall(PetscFVView((PetscFV)obj, viewer));
158: PetscCall(PetscViewerASCIIPopTab(viewer));
160: for (b = ds->boundary; b; b = b->next) {
161: char *name;
162: PetscInt c, i;
164: if (b->field != f) continue;
165: PetscCall(PetscViewerASCIIPushTab(viewer));
166: PetscCall(PetscViewerASCIIPrintf(viewer, "Boundary %s (%s) %s\n", b->name, b->lname, DMBoundaryConditionTypes[b->type]));
167: if (!b->Nc) {
168: PetscCall(PetscViewerASCIIPrintf(viewer, " all components\n"));
169: } else {
170: PetscCall(PetscViewerASCIIPrintf(viewer, " components: "));
171: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
172: for (c = 0; c < b->Nc; ++c) {
173: if (c > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
174: PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT, b->comps[c]));
175: }
176: PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
177: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
178: }
179: PetscCall(PetscViewerASCIIPrintf(viewer, " values: "));
180: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
181: for (i = 0; i < b->Nv; ++i) {
182: if (i > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
183: PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT, b->values[i]));
184: }
185: PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
186: PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
187: #if defined(__clang__)
188: PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN("-Wformat-pedantic")
189: #elif defined(__GNUC__) || defined(__GNUG__)
190: PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN("-Wformat")
191: #endif
192: if (b->func) {
193: PetscCall(PetscDLAddr(b->func, &name));
194: if (name) PetscCall(PetscViewerASCIIPrintf(viewer, " func: %s\n", name));
195: else PetscCall(PetscViewerASCIIPrintf(viewer, " func: %p\n", b->func));
196: PetscCall(PetscFree(name));
197: }
198: if (b->func_t) {
199: PetscCall(PetscDLAddr(b->func_t, &name));
200: if (name) PetscCall(PetscViewerASCIIPrintf(viewer, " func_t: %s\n", name));
201: else PetscCall(PetscViewerASCIIPrintf(viewer, " func_t: %p\n", b->func_t));
202: PetscCall(PetscFree(name));
203: }
204: PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END()
205: PetscCall(PetscWeakFormView(b->wf, viewer));
206: PetscCall(PetscViewerASCIIPopTab(viewer));
207: }
208: }
209: PetscCall(PetscDSGetConstants(ds, &numConstants, &constants));
210: if (numConstants) {
211: PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " constants\n", numConstants));
212: PetscCall(PetscViewerASCIIPushTab(viewer));
213: for (f = 0; f < numConstants; ++f) PetscCall(PetscViewerASCIIPrintf(viewer, "%g\n", (double)PetscRealPart(constants[f])));
214: PetscCall(PetscViewerASCIIPopTab(viewer));
215: }
216: PetscCall(PetscWeakFormView(ds->wf, viewer));
217: PetscCall(PetscViewerASCIIPopTab(viewer));
218: PetscFunctionReturn(PETSC_SUCCESS);
219: }
221: /*@
222: PetscDSViewFromOptions - View a `PetscDS` based on values in the options database
224: Collective
226: Input Parameters:
227: + A - the `PetscDS` object
228: . obj - Optional object that provides the options prefix used in the search of the options database
229: - name - command line option
231: Options Database Key:
232: . -name [viewertype][:...] - option name and values. See `PetscObjectViewFromOptions()` for the possible arguments
234: Level: intermediate
236: .seealso: `PetscDSType`, `PetscDS`, `PetscDSView()`, `PetscObjectViewFromOptions()`, `PetscDSCreate()`
237: @*/
238: PetscErrorCode PetscDSViewFromOptions(PetscDS A, PetscObject obj, const char name[])
239: {
240: PetscFunctionBegin;
242: PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
243: PetscFunctionReturn(PETSC_SUCCESS);
244: }
246: /*@
247: PetscDSView - Views a `PetscDS`
249: Collective
251: Input Parameters:
252: + prob - the `PetscDS` object to view
253: - v - the viewer
255: Level: developer
257: .seealso: `PetscDSType`, `PetscDS`, `PetscViewer`, `PetscDSDestroy()`, `PetscDSViewFromOptions()`
258: @*/
259: PetscErrorCode PetscDSView(PetscDS prob, PetscViewer v)
260: {
261: PetscBool isascii;
263: PetscFunctionBegin;
265: if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)prob), &v));
267: PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &isascii));
268: if (isascii) PetscCall(PetscDSView_Ascii(prob, v));
269: PetscTryTypeMethod(prob, view, v);
270: PetscFunctionReturn(PETSC_SUCCESS);
271: }
273: /*@
274: PetscDSSetFromOptions - sets parameters in a `PetscDS` from the options database
276: Collective
278: Input Parameter:
279: . prob - the `PetscDS` object to set options for
281: Options Database Keys:
282: + -petscds_type type - Set the `PetscDS` type
283: . -petscds_view - View the `PetscDS`
284: . -petscds_jac_pre (true|false) - Turn formation of a separate Jacobian preconditioner on or off
285: . -bc_NAME ids - comma separated list of label ids for the boundary condition NAME
286: - -bc_NAME_comp comps - comma separated list of field components to constrain for the boundary condition NAME
288: Level: intermediate
290: .seealso: `PetscDS`, `PetscDSView()`
291: @*/
292: PetscErrorCode PetscDSSetFromOptions(PetscDS prob)
293: {
294: DSBoundary b;
295: const char *defaultType;
296: char name[256];
297: PetscBool flg;
299: PetscFunctionBegin;
301: if (!((PetscObject)prob)->type_name) {
302: defaultType = PETSCDSBASIC;
303: } else {
304: defaultType = ((PetscObject)prob)->type_name;
305: }
306: PetscCall(PetscDSRegisterAll());
308: PetscObjectOptionsBegin((PetscObject)prob);
309: for (b = prob->boundary; b; b = b->next) {
310: char optname[1024];
311: PetscInt ids[1024], len = 1024;
312: PetscBool flg;
314: PetscCall(PetscSNPrintf(optname, sizeof(optname), "-bc_%s", b->name));
315: PetscCall(PetscMemzero(ids, sizeof(ids)));
316: PetscCall(PetscOptionsIntArray(optname, "List of boundary IDs", "", ids, &len, &flg));
317: if (flg) {
318: b->Nv = len;
319: PetscCall(PetscFree(b->values));
320: PetscCall(PetscMalloc1(len, &b->values));
321: PetscCall(PetscArraycpy(b->values, ids, len));
322: PetscCall(PetscWeakFormRewriteKeys(b->wf, b->label, len, b->values));
323: }
324: len = 1024;
325: PetscCall(PetscSNPrintf(optname, sizeof(optname), "-bc_%s_comp", b->name));
326: PetscCall(PetscMemzero(ids, sizeof(ids)));
327: PetscCall(PetscOptionsIntArray(optname, "List of boundary field components", "", ids, &len, &flg));
328: if (flg) {
329: b->Nc = len;
330: PetscCall(PetscFree(b->comps));
331: PetscCall(PetscMalloc1(len, &b->comps));
332: PetscCall(PetscArraycpy(b->comps, ids, len));
333: }
334: }
335: PetscCall(PetscOptionsFList("-petscds_type", "Discrete System", "PetscDSSetType", PetscDSList, defaultType, name, 256, &flg));
336: if (flg) {
337: PetscCall(PetscDSSetType(prob, name));
338: } else if (!((PetscObject)prob)->type_name) {
339: PetscCall(PetscDSSetType(prob, defaultType));
340: }
341: PetscCall(PetscOptionsBool("-petscds_jac_pre", "Discrete System", "PetscDSUseJacobianPreconditioner", prob->useJacPre, &prob->useJacPre, &flg));
342: PetscCall(PetscOptionsBool("-petscds_force_quad", "Discrete System", "PetscDSSetForceQuad", prob->forceQuad, &prob->forceQuad, &flg));
343: PetscCall(PetscOptionsInt("-petscds_print_integrate", "Discrete System", "", prob->printIntegrate, &prob->printIntegrate, NULL));
344: PetscTryTypeMethod(prob, setfromoptions);
345: /* process any options handlers added with PetscObjectAddOptionsHandler() */
346: PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)prob, PetscOptionsObject));
347: PetscOptionsEnd();
348: if (prob->Nf) PetscCall(PetscDSViewFromOptions(prob, NULL, "-petscds_view"));
349: PetscFunctionReturn(PETSC_SUCCESS);
350: }
352: /*@
353: PetscDSSetUp - Construct data structures for the `PetscDS`
355: Collective
357: Input Parameter:
358: . prob - the `PetscDS` object to setup
360: Level: developer
362: .seealso: `PetscDS`, `PetscDSView()`, `PetscDSDestroy()`
363: @*/
364: PetscErrorCode PetscDSSetUp(PetscDS prob)
365: {
366: const PetscInt Nf = prob->Nf;
367: PetscBool hasH = PETSC_FALSE;
368: PetscInt maxOrder[4] = {-2, -2, -2, -2};
369: PetscInt dim, dimEmbed, NbMax = 0, NcMax = 0, NqMax = 0, NsMax = 1, f;
371: PetscFunctionBegin;
373: if (prob->setup) PetscFunctionReturn(PETSC_SUCCESS);
374: /* Calculate sizes */
375: PetscCall(PetscDSGetSpatialDimension(prob, &dim));
376: PetscCall(PetscDSGetCoordinateDimension(prob, &dimEmbed));
377: prob->totDim = prob->totComp = 0;
378: PetscCall(PetscMalloc2(Nf, &prob->Nc, Nf, &prob->Nb));
379: PetscCall(PetscCalloc2(Nf + 1, &prob->off, Nf + 1, &prob->offDer));
380: 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]));
381: PetscCall(PetscMalloc2(Nf, &prob->T, Nf, &prob->Tf));
382: if (prob->forceQuad) {
383: // Note: This assumes we have one kind of cell at each dimension.
384: // We can fix this by having quadrature hold the celltype
385: PetscQuadrature maxQuad[4] = {NULL, NULL, NULL, NULL};
387: for (f = 0; f < Nf; ++f) {
388: PetscObject obj;
389: PetscClassId id;
390: PetscQuadrature q = NULL, fq = NULL;
391: PetscInt dim = -1, order = -1, forder = -1;
393: PetscCall(PetscDSGetDiscretization(prob, f, &obj));
394: if (!obj) continue;
395: PetscCall(PetscObjectGetClassId(obj, &id));
396: if (id == PETSCFE_CLASSID) {
397: PetscFE fe = (PetscFE)obj;
399: PetscCall(PetscFEGetQuadrature(fe, &q));
400: PetscCall(PetscFEGetFaceQuadrature(fe, &fq));
401: } else if (id == PETSCFV_CLASSID) {
402: PetscFV fv = (PetscFV)obj;
404: PetscCall(PetscFVGetQuadrature(fv, &q));
405: }
406: if (q) {
407: PetscCall(PetscQuadratureGetData(q, &dim, NULL, NULL, NULL, NULL));
408: PetscCall(PetscQuadratureGetOrder(q, &order));
409: if (order > maxOrder[dim]) {
410: maxOrder[dim] = order;
411: maxQuad[dim] = q;
412: }
413: }
414: if (fq) {
415: PetscCall(PetscQuadratureGetData(fq, &dim, NULL, NULL, NULL, NULL));
416: PetscCall(PetscQuadratureGetOrder(fq, &forder));
417: if (forder > maxOrder[dim]) {
418: maxOrder[dim] = forder;
419: maxQuad[dim] = fq;
420: }
421: }
422: }
423: for (f = 0; f < Nf; ++f) {
424: PetscObject obj;
425: PetscClassId id;
426: PetscQuadrature q;
427: PetscInt dim;
429: PetscCall(PetscDSGetDiscretization(prob, f, &obj));
430: if (!obj) continue;
431: PetscCall(PetscObjectGetClassId(obj, &id));
432: if (id == PETSCFE_CLASSID) {
433: PetscFE fe = (PetscFE)obj;
435: PetscCall(PetscFEGetQuadrature(fe, &q));
436: PetscCall(PetscQuadratureGetData(q, &dim, NULL, NULL, NULL, NULL));
437: PetscCall(PetscFESetQuadrature(fe, maxQuad[dim]));
438: PetscCall(PetscFESetFaceQuadrature(fe, dim ? maxQuad[dim - 1] : NULL));
439: } else if (id == PETSCFV_CLASSID) {
440: PetscFV fv = (PetscFV)obj;
442: PetscCall(PetscFVGetQuadrature(fv, &q));
443: PetscCall(PetscQuadratureGetData(q, &dim, NULL, NULL, NULL, NULL));
444: PetscCall(PetscFVSetQuadrature(fv, maxQuad[dim]));
445: }
446: }
447: }
448: for (f = 0; f < Nf; ++f) {
449: PetscObject obj;
450: PetscClassId id;
451: PetscQuadrature q = NULL;
452: PetscInt Nq = 0, Nb, Nc;
454: PetscCall(PetscDSGetDiscretization(prob, f, &obj));
455: if (prob->jetDegree[f] > 1) hasH = PETSC_TRUE;
456: if (!obj) {
457: /* Empty mesh */
458: Nb = Nc = 0;
459: prob->T[f] = prob->Tf[f] = NULL;
460: } else {
461: PetscCall(PetscObjectGetClassId(obj, &id));
462: if (id == PETSCFE_CLASSID) {
463: PetscFE fe = (PetscFE)obj;
465: PetscCall(PetscFEGetQuadrature(fe, &q));
466: {
467: PetscQuadrature fq;
468: PetscInt dim, order;
470: PetscCall(PetscQuadratureGetData(q, &dim, NULL, NULL, NULL, NULL));
471: PetscCall(PetscQuadratureGetOrder(q, &order));
472: if (maxOrder[dim] < 0) maxOrder[dim] = order;
473: 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]);
474: PetscCall(PetscFEGetFaceQuadrature(fe, &fq));
475: if (fq) {
476: PetscCall(PetscQuadratureGetData(fq, &dim, NULL, NULL, NULL, NULL));
477: PetscCall(PetscQuadratureGetOrder(fq, &order));
478: if (maxOrder[dim] < 0) maxOrder[dim] = order;
479: 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]);
480: }
481: }
482: PetscCall(PetscFEGetDimension(fe, &Nb));
483: PetscCall(PetscFEGetNumComponents(fe, &Nc));
484: PetscCall(PetscFEGetCellTabulation(fe, prob->jetDegree[f], &prob->T[f]));
485: PetscCall(PetscFEGetFaceTabulation(fe, prob->jetDegree[f], &prob->Tf[f]));
486: } else if (id == PETSCFV_CLASSID) {
487: PetscFV fv = (PetscFV)obj;
489: PetscCall(PetscFVGetQuadrature(fv, &q));
490: PetscCall(PetscFVGetNumComponents(fv, &Nc));
491: Nb = Nc;
492: PetscCall(PetscFVGetCellTabulation(fv, &prob->T[f]));
493: /* TODO: should PetscFV also have face tabulation? Otherwise there will be a null pointer in prob->basisFace */
494: } else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, f);
495: }
496: prob->Nc[f] = Nc;
497: prob->Nb[f] = Nb;
498: prob->off[f + 1] = Nc + prob->off[f];
499: prob->offDer[f + 1] = Nc * dim + prob->offDer[f];
500: prob->offCohesive[0][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) + prob->offCohesive[0][f];
501: prob->offDerCohesive[0][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) * dimEmbed + prob->offDerCohesive[0][f];
502: prob->offCohesive[1][f] = (prob->cohesive[f] ? 0 : Nc) + prob->offCohesive[0][f];
503: prob->offDerCohesive[1][f] = (prob->cohesive[f] ? 0 : Nc) * dimEmbed + prob->offDerCohesive[0][f];
504: prob->offCohesive[2][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) + prob->offCohesive[2][f];
505: prob->offDerCohesive[2][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) * dimEmbed + prob->offDerCohesive[2][f];
506: if (q) PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Nq, NULL, NULL));
507: NqMax = PetscMax(NqMax, Nq);
508: NbMax = PetscMax(NbMax, Nb);
509: NcMax = PetscMax(NcMax, Nc);
510: prob->totDim += Nb;
511: prob->totComp += Nc;
512: /* There are two faces for all fields on a cohesive cell, except for cohesive fields */
513: if (prob->isCohesive && !prob->cohesive[f]) prob->totDim += Nb;
514: }
515: prob->offCohesive[1][Nf] = prob->offCohesive[0][Nf];
516: prob->offDerCohesive[1][Nf] = prob->offDerCohesive[0][Nf];
517: /* Allocate works space */
518: NsMax = 2; /* A non-cohesive discretizations can be used on a cohesive cell, so we need this extra workspace for all DS */
519: 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));
520: PetscCall(PetscMalloc5(dimEmbed, &prob->x, NbMax * NcMax, &prob->basisReal, NbMax * NcMax * dimEmbed, &prob->basisDerReal, NbMax * NcMax, &prob->testReal, NbMax * NcMax * dimEmbed, &prob->testDerReal));
521: 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,
522: &prob->g2, NsMax * NsMax * NqMax * NcMax * NcMax * dimEmbed * dimEmbed, &prob->g3));
523: PetscTryTypeMethod(prob, setup);
524: prob->setup = PETSC_TRUE;
525: PetscFunctionReturn(PETSC_SUCCESS);
526: }
528: static PetscErrorCode PetscDSDestroyStructs_Static(PetscDS prob)
529: {
530: PetscFunctionBegin;
531: PetscCall(PetscFree2(prob->Nc, prob->Nb));
532: PetscCall(PetscFree2(prob->off, prob->offDer));
533: PetscCall(PetscFree6(prob->offCohesive[0], prob->offCohesive[1], prob->offCohesive[2], prob->offDerCohesive[0], prob->offDerCohesive[1], prob->offDerCohesive[2]));
534: PetscCall(PetscFree2(prob->T, prob->Tf));
535: PetscCall(PetscFree3(prob->u, prob->u_t, prob->u_x));
536: PetscCall(PetscFree5(prob->x, prob->basisReal, prob->basisDerReal, prob->testReal, prob->testDerReal));
537: PetscCall(PetscFree6(prob->f0, prob->f1, prob->g0, prob->g1, prob->g2, prob->g3));
538: PetscFunctionReturn(PETSC_SUCCESS);
539: }
541: static PetscErrorCode PetscDSEnlarge_Static(PetscDS prob, PetscInt NfNew)
542: {
543: PetscObject *tmpd;
544: PetscBool *tmpi;
545: PetscInt *tmpk;
546: PetscBool *tmpc;
547: PetscPointFn **tmpup;
548: PetscSimplePointFn **tmpexactSol, **tmpexactSol_t, **tmplowerBound, **tmpupperBound;
549: void **tmpexactCtx, **tmpexactCtx_t, **tmplowerCtx, **tmpupperCtx;
550: void **tmpctx;
551: PetscInt Nf = prob->Nf, f;
553: PetscFunctionBegin;
554: if (Nf >= NfNew) PetscFunctionReturn(PETSC_SUCCESS);
555: prob->setup = PETSC_FALSE;
556: PetscCall(PetscDSDestroyStructs_Static(prob));
557: PetscCall(PetscMalloc4(NfNew, &tmpd, NfNew, &tmpi, NfNew, &tmpc, NfNew, &tmpk));
558: for (f = 0; f < Nf; ++f) {
559: tmpd[f] = prob->disc[f];
560: tmpi[f] = prob->implicit[f];
561: tmpc[f] = prob->cohesive[f];
562: tmpk[f] = prob->jetDegree[f];
563: }
564: for (f = Nf; f < NfNew; ++f) {
565: tmpd[f] = NULL;
566: tmpi[f] = PETSC_TRUE, tmpc[f] = PETSC_FALSE;
567: tmpk[f] = 1;
568: }
569: PetscCall(PetscFree4(prob->disc, prob->implicit, prob->cohesive, prob->jetDegree));
570: PetscCall(PetscWeakFormSetNumFields(prob->wf, NfNew));
571: prob->Nf = NfNew;
572: prob->disc = tmpd;
573: prob->implicit = tmpi;
574: prob->cohesive = tmpc;
575: prob->jetDegree = tmpk;
576: PetscCall(PetscCalloc2(NfNew, &tmpup, NfNew, &tmpctx));
577: for (f = 0; f < Nf; ++f) tmpup[f] = prob->update[f];
578: for (f = 0; f < Nf; ++f) tmpctx[f] = prob->ctx[f];
579: for (f = Nf; f < NfNew; ++f) tmpup[f] = NULL;
580: for (f = Nf; f < NfNew; ++f) tmpctx[f] = NULL;
581: PetscCall(PetscFree2(prob->update, prob->ctx));
582: prob->update = tmpup;
583: prob->ctx = tmpctx;
584: PetscCall(PetscCalloc4(NfNew, &tmpexactSol, NfNew, &tmpexactCtx, NfNew, &tmpexactSol_t, NfNew, &tmpexactCtx_t));
585: PetscCall(PetscCalloc4(NfNew, &tmplowerBound, NfNew, &tmplowerCtx, NfNew, &tmpupperBound, NfNew, &tmpupperCtx));
586: for (f = 0; f < Nf; ++f) tmpexactSol[f] = prob->exactSol[f];
587: for (f = 0; f < Nf; ++f) tmpexactCtx[f] = prob->exactCtx[f];
588: for (f = 0; f < Nf; ++f) tmpexactSol_t[f] = prob->exactSol_t[f];
589: for (f = 0; f < Nf; ++f) tmpexactCtx_t[f] = prob->exactCtx_t[f];
590: for (f = 0; f < Nf; ++f) tmplowerBound[f] = prob->lowerBound[f];
591: for (f = 0; f < Nf; ++f) tmplowerCtx[f] = prob->lowerCtx[f];
592: for (f = 0; f < Nf; ++f) tmpupperBound[f] = prob->upperBound[f];
593: for (f = 0; f < Nf; ++f) tmpupperCtx[f] = prob->upperCtx[f];
594: for (f = Nf; f < NfNew; ++f) tmpexactSol[f] = NULL;
595: for (f = Nf; f < NfNew; ++f) tmpexactCtx[f] = NULL;
596: for (f = Nf; f < NfNew; ++f) tmpexactSol_t[f] = NULL;
597: for (f = Nf; f < NfNew; ++f) tmpexactCtx_t[f] = NULL;
598: for (f = Nf; f < NfNew; ++f) tmplowerBound[f] = NULL;
599: for (f = Nf; f < NfNew; ++f) tmplowerCtx[f] = NULL;
600: for (f = Nf; f < NfNew; ++f) tmpupperBound[f] = NULL;
601: for (f = Nf; f < NfNew; ++f) tmpupperCtx[f] = NULL;
602: PetscCall(PetscFree4(prob->exactSol, prob->exactCtx, prob->exactSol_t, prob->exactCtx_t));
603: PetscCall(PetscFree4(prob->lowerBound, prob->lowerCtx, prob->upperBound, prob->upperCtx));
604: prob->exactSol = tmpexactSol;
605: prob->exactCtx = tmpexactCtx;
606: prob->exactSol_t = tmpexactSol_t;
607: prob->exactCtx_t = tmpexactCtx_t;
608: prob->lowerBound = tmplowerBound;
609: prob->lowerCtx = tmplowerCtx;
610: prob->upperBound = tmpupperBound;
611: prob->upperCtx = tmpupperCtx;
612: PetscFunctionReturn(PETSC_SUCCESS);
613: }
615: /*@
616: PetscDSDestroy - Destroys a `PetscDS` object
618: Collective
620: Input Parameter:
621: . ds - the `PetscDS` object to destroy
623: Level: developer
625: .seealso: `PetscDSView()`
626: @*/
627: PetscErrorCode PetscDSDestroy(PetscDS *ds)
628: {
629: PetscInt f;
631: PetscFunctionBegin;
632: if (!*ds) PetscFunctionReturn(PETSC_SUCCESS);
635: if (--((PetscObject)*ds)->refct > 0) {
636: *ds = NULL;
637: PetscFunctionReturn(PETSC_SUCCESS);
638: }
639: ((PetscObject)*ds)->refct = 0;
640: if ((*ds)->subprobs) {
641: PetscInt dim, d;
643: PetscCall(PetscDSGetSpatialDimension(*ds, &dim));
644: for (d = 0; d < dim; ++d) PetscCall(PetscDSDestroy(&(*ds)->subprobs[d]));
645: }
646: PetscCall(PetscFree((*ds)->subprobs));
647: PetscCall(PetscDSDestroyStructs_Static(*ds));
648: for (f = 0; f < (*ds)->Nf; ++f) PetscCall(PetscObjectDereference((*ds)->disc[f]));
649: PetscCall(PetscFree4((*ds)->disc, (*ds)->implicit, (*ds)->cohesive, (*ds)->jetDegree));
650: PetscCall(PetscWeakFormDestroy(&(*ds)->wf));
651: PetscCall(PetscFree2((*ds)->update, (*ds)->ctx));
652: PetscCall(PetscFree4((*ds)->exactSol, (*ds)->exactCtx, (*ds)->exactSol_t, (*ds)->exactCtx_t));
653: PetscCall(PetscFree4((*ds)->lowerBound, (*ds)->lowerCtx, (*ds)->upperBound, (*ds)->upperCtx));
654: PetscTryTypeMethod(*ds, destroy);
655: PetscCall(PetscDSDestroyBoundary(*ds));
656: PetscCall(PetscFree((*ds)->constants));
657: for (PetscInt c = 0; c < DM_NUM_POLYTOPES; ++c) {
658: const PetscInt Na = DMPolytopeTypeGetNumArrangements((DMPolytopeType)c);
659: if ((*ds)->quadPerm[c])
660: for (PetscInt o = 0; o < Na; ++o) PetscCall(ISDestroy(&(*ds)->quadPerm[c][o]));
661: PetscCall(PetscFree((*ds)->quadPerm[c]));
662: (*ds)->quadPerm[c] = NULL;
663: }
664: PetscCall(PetscHeaderDestroy(ds));
665: PetscFunctionReturn(PETSC_SUCCESS);
666: }
668: /*@
669: PetscDSCreate - Creates an empty `PetscDS` object. The type can then be set with `PetscDSSetType()`.
671: Collective
673: Input Parameter:
674: . comm - The communicator for the `PetscDS` object
676: Output Parameter:
677: . ds - The `PetscDS` object
679: Level: beginner
681: .seealso: `PetscDS`, `PetscDSSetType()`, `PETSCDSBASIC`, `PetscDSType`, `PetscDSDestroy()`
682: @*/
683: PetscErrorCode PetscDSCreate(MPI_Comm comm, PetscDS *ds)
684: {
685: PetscDS p;
687: PetscFunctionBegin;
688: PetscAssertPointer(ds, 2);
689: PetscCall(PetscDSInitializePackage());
691: PetscCall(PetscHeaderCreate(p, PETSCDS_CLASSID, "PetscDS", "Discrete System", "PetscDS", comm, PetscDSDestroy, PetscDSView));
692: p->Nf = 0;
693: p->setup = PETSC_FALSE;
694: p->numConstants = 0;
695: p->numFuncConstants = 3; // Row and col fields, cell size
696: p->dimEmbed = -1;
697: p->useJacPre = PETSC_TRUE;
698: p->forceQuad = PETSC_TRUE;
699: PetscCall(PetscMalloc1(p->numConstants + p->numFuncConstants, &p->constants));
700: PetscCall(PetscWeakFormCreate(comm, &p->wf));
701: PetscCall(PetscArrayzero(p->quadPerm, DM_NUM_POLYTOPES));
702: *ds = p;
703: PetscFunctionReturn(PETSC_SUCCESS);
704: }
706: /*@
707: PetscDSGetNumFields - Returns the number of fields in the `PetscDS`
709: Not Collective
711: Input Parameter:
712: . prob - The `PetscDS` object
714: Output Parameter:
715: . Nf - The number of fields
717: Level: beginner
719: .seealso: `PetscDS`, `PetscDSGetSpatialDimension()`, `PetscDSCreate()`
720: @*/
721: PetscErrorCode PetscDSGetNumFields(PetscDS prob, PetscInt *Nf)
722: {
723: PetscFunctionBegin;
725: PetscAssertPointer(Nf, 2);
726: *Nf = prob->Nf;
727: PetscFunctionReturn(PETSC_SUCCESS);
728: }
730: /*@
731: PetscDSGetSpatialDimension - Returns the spatial dimension of the `PetscDS`, meaning the topological dimension of the discretizations
733: Not Collective
735: Input Parameter:
736: . prob - The `PetscDS` object
738: Output Parameter:
739: . dim - The spatial dimension
741: Level: beginner
743: .seealso: `PetscDS`, `PetscDSGetCoordinateDimension()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
744: @*/
745: PetscErrorCode PetscDSGetSpatialDimension(PetscDS prob, PetscInt *dim)
746: {
747: PetscFunctionBegin;
749: PetscAssertPointer(dim, 2);
750: *dim = 0;
751: if (prob->Nf) {
752: PetscObject obj;
753: PetscClassId id;
755: PetscCall(PetscDSGetDiscretization(prob, 0, &obj));
756: if (obj) {
757: PetscCall(PetscObjectGetClassId(obj, &id));
758: if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetSpatialDimension((PetscFE)obj, dim));
759: else if (id == PETSCFV_CLASSID) PetscCall(PetscFVGetSpatialDimension((PetscFV)obj, dim));
760: else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
761: }
762: }
763: PetscFunctionReturn(PETSC_SUCCESS);
764: }
766: /*@
767: PetscDSGetCoordinateDimension - Returns the coordinate dimension of the `PetscDS`, meaning the dimension of the space into which the discretiaztions are embedded
769: Not Collective
771: Input Parameter:
772: . prob - The `PetscDS` object
774: Output Parameter:
775: . dimEmbed - The coordinate dimension
777: Level: beginner
779: .seealso: `PetscDS`, `PetscDSSetCoordinateDimension()`, `PetscDSGetSpatialDimension()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
780: @*/
781: PetscErrorCode PetscDSGetCoordinateDimension(PetscDS prob, PetscInt *dimEmbed)
782: {
783: PetscFunctionBegin;
785: PetscAssertPointer(dimEmbed, 2);
786: PetscCheck(prob->dimEmbed >= 0, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONGSTATE, "No coordinate dimension set for this DS");
787: *dimEmbed = prob->dimEmbed;
788: PetscFunctionReturn(PETSC_SUCCESS);
789: }
791: /*@
792: PetscDSSetCoordinateDimension - Set the coordinate dimension of the `PetscDS`, meaning the dimension of the space into which the discretiaztions are embedded
794: Logically Collective
796: Input Parameters:
797: + prob - The `PetscDS` object
798: - dimEmbed - The coordinate dimension
800: Level: beginner
802: .seealso: `PetscDS`, `PetscDSGetCoordinateDimension()`, `PetscDSGetSpatialDimension()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
803: @*/
804: PetscErrorCode PetscDSSetCoordinateDimension(PetscDS prob, PetscInt dimEmbed)
805: {
806: PetscFunctionBegin;
808: PetscCheck(dimEmbed >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate dimension must be non-negative, not %" PetscInt_FMT, dimEmbed);
809: prob->dimEmbed = dimEmbed;
810: PetscFunctionReturn(PETSC_SUCCESS);
811: }
813: /*@
814: PetscDSGetForceQuad - Returns the flag to force matching quadratures among the field discretizations
816: Not collective
818: Input Parameter:
819: . ds - The `PetscDS` object
821: Output Parameter:
822: . forceQuad - The flag
824: Level: intermediate
826: .seealso: `PetscDS`, `PetscDSSetForceQuad()`, `PetscDSGetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
827: @*/
828: PetscErrorCode PetscDSGetForceQuad(PetscDS ds, PetscBool *forceQuad)
829: {
830: PetscFunctionBegin;
832: PetscAssertPointer(forceQuad, 2);
833: *forceQuad = ds->forceQuad;
834: PetscFunctionReturn(PETSC_SUCCESS);
835: }
837: /*@
838: PetscDSSetForceQuad - Set the flag to force matching quadratures among the field discretizations
840: Logically collective on ds
842: Input Parameters:
843: + ds - The `PetscDS` object
844: - forceQuad - The flag
846: Level: intermediate
848: .seealso: `PetscDS`, `PetscDSGetForceQuad()`, `PetscDSGetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
849: @*/
850: PetscErrorCode PetscDSSetForceQuad(PetscDS ds, PetscBool forceQuad)
851: {
852: PetscFunctionBegin;
854: ds->forceQuad = forceQuad;
855: PetscFunctionReturn(PETSC_SUCCESS);
856: }
858: /*@
859: PetscDSIsCohesive - Returns the flag indicating that this `PetscDS` is for a cohesive cell
861: Not Collective
863: Input Parameter:
864: . ds - The `PetscDS` object
866: Output Parameter:
867: . isCohesive - The flag
869: Level: developer
871: .seealso: `PetscDS`, `PetscDSGetNumCohesive()`, `PetscDSGetCohesive()`, `PetscDSSetCohesive()`, `PetscDSCreate()`
872: @*/
873: PetscErrorCode PetscDSIsCohesive(PetscDS ds, PetscBool *isCohesive)
874: {
875: PetscFunctionBegin;
877: PetscAssertPointer(isCohesive, 2);
878: *isCohesive = ds->isCohesive;
879: PetscFunctionReturn(PETSC_SUCCESS);
880: }
882: /*@
883: PetscDSGetNumCohesive - Returns the number of cohesive fields, meaning those defined on the interior of a cohesive cell
885: Not Collective
887: Input Parameter:
888: . ds - The `PetscDS` object
890: Output Parameter:
891: . numCohesive - The number of cohesive fields
893: Level: developer
895: .seealso: `PetscDS`, `PetscDSSetCohesive()`, `PetscDSCreate()`
896: @*/
897: PetscErrorCode PetscDSGetNumCohesive(PetscDS ds, PetscInt *numCohesive)
898: {
899: PetscInt f;
901: PetscFunctionBegin;
903: PetscAssertPointer(numCohesive, 2);
904: *numCohesive = 0;
905: for (f = 0; f < ds->Nf; ++f) *numCohesive += ds->cohesive[f] ? 1 : 0;
906: PetscFunctionReturn(PETSC_SUCCESS);
907: }
909: /*@
910: PetscDSGetCohesive - Returns the flag indicating that a field is cohesive, meaning it is defined on the interior of a cohesive cell
912: Not Collective
914: Input Parameters:
915: + ds - The `PetscDS` object
916: - f - The field index
918: Output Parameter:
919: . isCohesive - The flag
921: Level: developer
923: .seealso: `PetscDS`, `PetscDSSetCohesive()`, `PetscDSIsCohesive()`, `PetscDSCreate()`
924: @*/
925: PetscErrorCode PetscDSGetCohesive(PetscDS ds, PetscInt f, PetscBool *isCohesive)
926: {
927: PetscFunctionBegin;
929: PetscAssertPointer(isCohesive, 3);
930: 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);
931: *isCohesive = ds->cohesive[f];
932: PetscFunctionReturn(PETSC_SUCCESS);
933: }
935: /*@
936: PetscDSSetCohesive - Set the flag indicating that a field is cohesive, meaning it is defined on the interior of a cohesive cell
938: Not Collective
940: Input Parameters:
941: + ds - The `PetscDS` object
942: . f - The field index
943: - isCohesive - The flag for a cohesive field
945: Level: developer
947: .seealso: `PetscDS`, `PetscDSGetCohesive()`, `PetscDSIsCohesive()`, `PetscDSCreate()`
948: @*/
949: PetscErrorCode PetscDSSetCohesive(PetscDS ds, PetscInt f, PetscBool isCohesive)
950: {
951: PetscInt i;
953: PetscFunctionBegin;
955: 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);
956: ds->cohesive[f] = isCohesive;
957: ds->isCohesive = PETSC_FALSE;
958: for (i = 0; i < ds->Nf; ++i) ds->isCohesive = ds->isCohesive || ds->cohesive[f] ? PETSC_TRUE : PETSC_FALSE;
959: PetscFunctionReturn(PETSC_SUCCESS);
960: }
962: /*@
963: PetscDSGetTotalDimension - Returns the total size of the approximation space for this system
965: Not Collective
967: Input Parameter:
968: . prob - The `PetscDS` object
970: Output Parameter:
971: . dim - The total problem dimension
973: Level: beginner
975: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
976: @*/
977: PetscErrorCode PetscDSGetTotalDimension(PetscDS prob, PetscInt *dim)
978: {
979: PetscFunctionBegin;
981: PetscCall(PetscDSSetUp(prob));
982: PetscAssertPointer(dim, 2);
983: *dim = prob->totDim;
984: PetscFunctionReturn(PETSC_SUCCESS);
985: }
987: /*@
988: PetscDSGetTotalComponents - Returns the total number of components in this system
990: Not Collective
992: Input Parameter:
993: . prob - The `PetscDS` object
995: Output Parameter:
996: . Nc - The total number of components
998: Level: beginner
1000: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1001: @*/
1002: PetscErrorCode PetscDSGetTotalComponents(PetscDS prob, PetscInt *Nc)
1003: {
1004: PetscFunctionBegin;
1006: PetscCall(PetscDSSetUp(prob));
1007: PetscAssertPointer(Nc, 2);
1008: *Nc = prob->totComp;
1009: PetscFunctionReturn(PETSC_SUCCESS);
1010: }
1012: /*@
1013: PetscDSGetDiscretization - Returns the discretization object for the given field
1015: Not Collective
1017: Input Parameters:
1018: + prob - The `PetscDS` object
1019: - f - The field number
1021: Output Parameter:
1022: . disc - The discretization object, this can be a `PetscFE` or a `PetscFV`
1024: Level: beginner
1026: .seealso: `PetscDS`, `PetscFE`, `PetscFV`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1027: @*/
1028: PetscErrorCode PetscDSGetDiscretization(PetscDS prob, PetscInt f, PetscObject *disc)
1029: {
1030: PetscFunctionBeginHot;
1032: PetscAssertPointer(disc, 3);
1033: 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);
1034: *disc = prob->disc[f];
1035: PetscFunctionReturn(PETSC_SUCCESS);
1036: }
1038: /*@
1039: PetscDSSetDiscretization - Sets the discretization object for the given field
1041: Not Collective
1043: Input Parameters:
1044: + prob - The `PetscDS` object
1045: . f - The field number
1046: - disc - The discretization object, this can be a `PetscFE` or a `PetscFV`
1048: Level: beginner
1050: .seealso: `PetscDS`, `PetscFE`, `PetscFV`, `PetscDSGetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1051: @*/
1052: PetscErrorCode PetscDSSetDiscretization(PetscDS prob, PetscInt f, PetscObject disc)
1053: {
1054: PetscFunctionBegin;
1056: if (disc) PetscAssertPointer(disc, 3);
1057: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1058: PetscCall(PetscDSEnlarge_Static(prob, f + 1));
1059: PetscCall(PetscObjectDereference(prob->disc[f]));
1060: prob->disc[f] = disc;
1061: PetscCall(PetscObjectReference(disc));
1062: if (disc) {
1063: PetscClassId id;
1065: PetscCall(PetscObjectGetClassId(disc, &id));
1066: if (id == PETSCFE_CLASSID) {
1067: PetscCall(PetscDSSetImplicit(prob, f, PETSC_TRUE));
1068: } else if (id == PETSCFV_CLASSID) {
1069: PetscCall(PetscDSSetImplicit(prob, f, PETSC_FALSE));
1070: }
1071: PetscCall(PetscDSSetJetDegree(prob, f, 1));
1072: }
1073: PetscFunctionReturn(PETSC_SUCCESS);
1074: }
1076: /*@
1077: PetscDSGetWeakForm - Returns the weak form object from within the `PetscDS`
1079: Not Collective
1081: Input Parameter:
1082: . ds - The `PetscDS` object
1084: Output Parameter:
1085: . wf - The weak form object
1087: Level: beginner
1089: .seealso: `PetscWeakForm`, `PetscDSSetWeakForm()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1090: @*/
1091: PetscErrorCode PetscDSGetWeakForm(PetscDS ds, PetscWeakForm *wf)
1092: {
1093: PetscFunctionBegin;
1095: PetscAssertPointer(wf, 2);
1096: *wf = ds->wf;
1097: PetscFunctionReturn(PETSC_SUCCESS);
1098: }
1100: /*@
1101: PetscDSSetWeakForm - Sets the weak form object to be used by the `PetscDS`
1103: Not Collective
1105: Input Parameters:
1106: + ds - The `PetscDS` object
1107: - wf - The weak form object
1109: Level: beginner
1111: .seealso: `PetscWeakForm`, `PetscDSGetWeakForm()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1112: @*/
1113: PetscErrorCode PetscDSSetWeakForm(PetscDS ds, PetscWeakForm wf)
1114: {
1115: PetscFunctionBegin;
1118: PetscCall(PetscObjectDereference((PetscObject)ds->wf));
1119: ds->wf = wf;
1120: PetscCall(PetscObjectReference((PetscObject)wf));
1121: PetscCall(PetscWeakFormSetNumFields(wf, ds->Nf));
1122: PetscFunctionReturn(PETSC_SUCCESS);
1123: }
1125: /*@
1126: PetscDSAddDiscretization - Adds a discretization object
1128: Not Collective
1130: Input Parameters:
1131: + prob - The `PetscDS` object
1132: - disc - The discretization object, this can be a `PetscFE` or `PetscFV`
1134: Level: beginner
1136: .seealso: `PetscWeakForm`, `PetscFE`, `PetscFV`, `PetscDSGetDiscretization()`, `PetscDSSetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1137: @*/
1138: PetscErrorCode PetscDSAddDiscretization(PetscDS prob, PetscObject disc)
1139: {
1140: PetscFunctionBegin;
1141: PetscCall(PetscDSSetDiscretization(prob, prob->Nf, disc));
1142: PetscFunctionReturn(PETSC_SUCCESS);
1143: }
1145: /*@
1146: PetscDSGetQuadrature - Returns the quadrature, which must agree for all fields in the `PetscDS`
1148: Not Collective
1150: Input Parameter:
1151: . prob - The `PetscDS` object
1153: Output Parameter:
1154: . q - The quadrature object
1156: Level: intermediate
1158: .seealso: `PetscDS`, `PetscQuadrature`, `PetscDSSetImplicit()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1159: @*/
1160: PetscErrorCode PetscDSGetQuadrature(PetscDS prob, PetscQuadrature *q)
1161: {
1162: PetscObject obj;
1163: PetscClassId id;
1165: PetscFunctionBegin;
1166: *q = NULL;
1167: if (!prob->Nf) PetscFunctionReturn(PETSC_SUCCESS);
1168: PetscCall(PetscDSGetDiscretization(prob, 0, &obj));
1169: PetscCall(PetscObjectGetClassId(obj, &id));
1170: if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetQuadrature((PetscFE)obj, q));
1171: else if (id == PETSCFV_CLASSID) PetscCall(PetscFVGetQuadrature((PetscFV)obj, q));
1172: else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0);
1173: PetscFunctionReturn(PETSC_SUCCESS);
1174: }
1176: /*@
1177: PetscDSGetImplicit - Returns the flag for implicit solve for this field. This is just a guide for `TSARKIMEX`
1179: Not Collective
1181: Input Parameters:
1182: + prob - The `PetscDS` object
1183: - f - The field number
1185: Output Parameter:
1186: . implicit - The flag indicating what kind of solve to use for this field
1188: Level: developer
1190: .seealso: `TSARKIMEX`, `PetscDS`, `PetscDSSetImplicit()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1191: @*/
1192: PetscErrorCode PetscDSGetImplicit(PetscDS prob, PetscInt f, PetscBool *implicit)
1193: {
1194: PetscFunctionBegin;
1196: PetscAssertPointer(implicit, 3);
1197: 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);
1198: *implicit = prob->implicit[f];
1199: PetscFunctionReturn(PETSC_SUCCESS);
1200: }
1202: /*@
1203: PetscDSSetImplicit - Set the flag for implicit solve for this field. This is just a guide for `TSARKIMEX`
1205: Not Collective
1207: Input Parameters:
1208: + prob - The `PetscDS` object
1209: . f - The field number
1210: - implicit - The flag indicating what kind of solve to use for this field
1212: Level: developer
1214: .seealso: `TSARKIMEX`, `PetscDSGetImplicit()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1215: @*/
1216: PetscErrorCode PetscDSSetImplicit(PetscDS prob, PetscInt f, PetscBool implicit)
1217: {
1218: PetscFunctionBegin;
1220: 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);
1221: prob->implicit[f] = implicit;
1222: PetscFunctionReturn(PETSC_SUCCESS);
1223: }
1225: /*@
1226: PetscDSGetJetDegree - Returns the highest derivative for this field equation, or the k-jet that the discretization needs to tabulate.
1228: Not Collective
1230: Input Parameters:
1231: + ds - The `PetscDS` object
1232: - f - The field number
1234: Output Parameter:
1235: . k - The highest derivative we need to tabulate
1237: Level: developer
1239: .seealso: `PetscDS`, `PetscDSSetJetDegree()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1240: @*/
1241: PetscErrorCode PetscDSGetJetDegree(PetscDS ds, PetscInt f, PetscInt *k)
1242: {
1243: PetscFunctionBegin;
1245: PetscAssertPointer(k, 3);
1246: 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);
1247: *k = ds->jetDegree[f];
1248: PetscFunctionReturn(PETSC_SUCCESS);
1249: }
1251: /*@
1252: PetscDSSetJetDegree - Set the highest derivative for this field equation, or the k-jet that the discretization needs to tabulate.
1254: Not Collective
1256: Input Parameters:
1257: + ds - The `PetscDS` object
1258: . f - The field number
1259: - k - The highest derivative we need to tabulate
1261: Level: developer
1263: .seealso: `PetscDS`, `PetscDSGetJetDegree()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
1264: @*/
1265: PetscErrorCode PetscDSSetJetDegree(PetscDS ds, PetscInt f, PetscInt k)
1266: {
1267: PetscFunctionBegin;
1269: 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);
1270: ds->jetDegree[f] = k;
1271: PetscFunctionReturn(PETSC_SUCCESS);
1272: }
1274: /*@C
1275: PetscDSGetObjective - Get the pointwise objective function for a given test field that was provided with `PetscDSSetObjective()`
1277: Not Collective
1279: Input Parameters:
1280: + ds - The `PetscDS`
1281: - f - The test field number
1283: Output Parameter:
1284: . obj - integrand for the test function term, see `PetscPointFn`
1286: Level: intermediate
1288: Note:
1289: We are using a first order FEM model for the weak form\: $ \int_\Omega \phi\,\mathrm{obj}(u, u_t, \nabla u, x, t)$
1291: .seealso: `PetscPointFn`, `PetscDS`, `PetscDSSetObjective()`, `PetscDSGetResidual()`
1292: @*/
1293: PetscErrorCode PetscDSGetObjective(PetscDS ds, PetscInt f, PetscPointFn **obj)
1294: {
1295: PetscPointFn **tmp;
1296: PetscInt n;
1298: PetscFunctionBegin;
1300: PetscAssertPointer(obj, 3);
1301: 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);
1302: PetscCall(PetscWeakFormGetObjective(ds->wf, NULL, 0, f, 0, &n, &tmp));
1303: *obj = tmp ? tmp[0] : NULL;
1304: PetscFunctionReturn(PETSC_SUCCESS);
1305: }
1307: /*@C
1308: PetscDSSetObjective - Set the pointwise objective function for a given test field
1310: Not Collective
1312: Input Parameters:
1313: + ds - The `PetscDS`
1314: . f - The test field number
1315: - obj - integrand for the test function term, see `PetscPointFn`
1317: Level: intermediate
1319: Note:
1320: We are using a first order FEM model for the weak form\: $ \int_\Omega \phi\,\mathrm{obj}(u, u_t, \nabla u, x, t)$
1322: .seealso: `PetscPointFn`, `PetscDS`, `PetscDSGetObjective()`, `PetscDSSetResidual()`
1323: @*/
1324: PetscErrorCode PetscDSSetObjective(PetscDS ds, PetscInt f, PetscPointFn *obj)
1325: {
1326: PetscFunctionBegin;
1329: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1330: PetscCall(PetscWeakFormSetIndexObjective(ds->wf, NULL, 0, f, 0, 0, obj));
1331: PetscFunctionReturn(PETSC_SUCCESS);
1332: }
1334: /*@C
1335: PetscDSGetResidual - Get the pointwise residual function for a given test field
1337: Not Collective
1339: Input Parameters:
1340: + ds - The `PetscDS`
1341: - f - The test field number
1343: Output Parameters:
1344: + f0 - integrand for the test function term, see `PetscPointFn`
1345: - f1 - integrand for the test function gradient term, see `PetscPointFn`
1347: Level: intermediate
1349: Note:
1350: 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)$
1352: .seealso: `PetscPointFn`, `PetscDS`, `PetscDSSetResidual()`
1353: @*/
1354: PetscErrorCode PetscDSGetResidual(PetscDS ds, PetscInt f, PetscPointFn **f0, PetscPointFn **f1)
1355: {
1356: PetscPointFn **tmp0, **tmp1;
1357: PetscInt n0, n1;
1359: PetscFunctionBegin;
1361: 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);
1362: PetscCall(PetscWeakFormGetResidual(ds->wf, NULL, 0, f, 0, &n0, &tmp0, &n1, &tmp1));
1363: *f0 = tmp0 ? tmp0[0] : NULL;
1364: *f1 = tmp1 ? tmp1[0] : NULL;
1365: PetscFunctionReturn(PETSC_SUCCESS);
1366: }
1368: /*@C
1369: PetscDSSetResidual - Set the pointwise residual function for a given test field
1371: Not Collective
1373: Input Parameters:
1374: + ds - The `PetscDS`
1375: . f - The test field number
1376: . f0 - integrand for the test function term, see `PetscPointFn`
1377: - f1 - integrand for the test function gradient term, see `PetscPointFn`
1379: Level: intermediate
1381: Note:
1382: We are using a first order FEM model for the weak form\: $ \int_\Omega \phi f_0(u, u_t, \nabla u, x, t) + \nabla\phi \cdot {\vec f}_1(u, u_t, \nabla u, x, t)$
1384: .seealso: `PetscPointFn`, `PetscDS`, `PetscDSGetResidual()`
1385: @*/
1386: PetscErrorCode PetscDSSetResidual(PetscDS ds, PetscInt f, PetscPointFn *f0, PetscPointFn *f1)
1387: {
1388: PetscFunctionBegin;
1392: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1393: PetscCall(PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1));
1394: PetscFunctionReturn(PETSC_SUCCESS);
1395: }
1397: /*@C
1398: PetscDSGetRHSResidual - Get the pointwise RHS residual function for explicit timestepping for a given test field
1400: Not Collective
1402: Input Parameters:
1403: + ds - The `PetscDS`
1404: - f - The test field number
1406: Output Parameters:
1407: + f0 - integrand for the test function term, see `PetscPointFn`
1408: - f1 - integrand for the test function gradient term, see `PetscPointFn`
1410: Level: intermediate
1412: Note:
1413: 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)$
1415: .seealso: `PetscPointFn`, `PetscDS`, `PetscDSSetRHSResidual()`
1416: @*/
1417: PetscErrorCode PetscDSGetRHSResidual(PetscDS ds, PetscInt f, PetscPointFn **f0, PetscPointFn **f1)
1418: {
1419: PetscPointFn **tmp0, **tmp1;
1420: PetscInt n0, n1;
1422: PetscFunctionBegin;
1424: 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);
1425: PetscCall(PetscWeakFormGetResidual(ds->wf, NULL, 0, f, 100, &n0, &tmp0, &n1, &tmp1));
1426: *f0 = tmp0 ? tmp0[0] : NULL;
1427: *f1 = tmp1 ? tmp1[0] : NULL;
1428: PetscFunctionReturn(PETSC_SUCCESS);
1429: }
1431: /*@C
1432: PetscDSSetRHSResidual - Set the pointwise residual function for explicit timestepping for a given test field
1434: Not Collective
1436: Input Parameters:
1437: + ds - The `PetscDS`
1438: . f - The test field number
1439: . f0 - integrand for the test function term, see `PetscPointFn`
1440: - f1 - integrand for the test function gradient term, see `PetscPointFn`
1442: Level: intermediate
1444: Note:
1445: 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)$
1447: .seealso: `PetscDS`, `PetscDSGetResidual()`
1448: @*/
1449: PetscErrorCode PetscDSSetRHSResidual(PetscDS ds, PetscInt f, PetscPointFn *f0, PetscPointFn *f1)
1450: {
1451: PetscFunctionBegin;
1455: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1456: PetscCall(PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 100, 0, f0, 0, f1));
1457: PetscFunctionReturn(PETSC_SUCCESS);
1458: }
1460: /*@
1461: PetscDSHasJacobian - Checks that the Jacobian functions have been set
1463: Not Collective
1465: Input Parameter:
1466: . ds - The `PetscDS`
1468: Output Parameter:
1469: . hasJac - flag that indicates the pointwise function for the Jacobian has been set
1471: Level: intermediate
1473: .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`
1474: @*/
1475: PetscErrorCode PetscDSHasJacobian(PetscDS ds, PetscBool *hasJac)
1476: {
1477: PetscFunctionBegin;
1479: PetscCall(PetscWeakFormHasJacobian(ds->wf, hasJac));
1480: PetscFunctionReturn(PETSC_SUCCESS);
1481: }
1483: /*@C
1484: PetscDSGetJacobian - Get the pointwise Jacobian function for given test and basis field
1486: Not Collective
1488: Input Parameters:
1489: + ds - The `PetscDS`
1490: . f - The test field number
1491: - g - The field number
1493: Output Parameters:
1494: + g0 - integrand for the test and basis function term, see `PetscPointJacFn`
1495: . g1 - integrand for the test function and basis function gradient term, see `PetscPointJacFn`
1496: . g2 - integrand for the test function gradient and basis function term, see `PetscPointJacFn`
1497: - g3 - integrand for the test function gradient and basis function gradient term, see `PetscPointJacFn`
1499: Level: intermediate
1501: Note:
1502: We are using a first order FEM model for the weak form\:
1504: $$
1505: \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
1506: + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \nabla \psi
1507: $$
1509: .seealso: `PetscDS`, `PetscDSSetJacobian()`, `PetscPointJacFn`
1510: @*/
1511: PetscErrorCode PetscDSGetJacobian(PetscDS ds, PetscInt f, PetscInt g, PetscPointJacFn **g0, PetscPointJacFn **g1, PetscPointJacFn **g2, PetscPointJacFn **g3)
1512: {
1513: PetscPointJacFn **tmp0, **tmp1, **tmp2, **tmp3;
1514: PetscInt n0, n1, n2, n3;
1516: PetscFunctionBegin;
1518: 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);
1519: 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);
1520: PetscCall(PetscWeakFormGetJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
1521: *g0 = tmp0 ? tmp0[0] : NULL;
1522: *g1 = tmp1 ? tmp1[0] : NULL;
1523: *g2 = tmp2 ? tmp2[0] : NULL;
1524: *g3 = tmp3 ? tmp3[0] : NULL;
1525: PetscFunctionReturn(PETSC_SUCCESS);
1526: }
1528: /*@C
1529: PetscDSSetJacobian - Set the pointwise Jacobian function for given test and basis fields
1531: Not Collective
1533: Input Parameters:
1534: + ds - The `PetscDS`
1535: . f - The test field number
1536: . g - The field number
1537: . g0 - integrand for the test and basis function term, see `PetscPointJacFn`
1538: . g1 - integrand for the test function and basis function gradient term, see `PetscPointJacFn`
1539: . g2 - integrand for the test function gradient and basis function term, see `PetscPointJacFn`
1540: - g3 - integrand for the test function gradient and basis function gradient term, see `PetscPointJacFn`
1542: Level: intermediate
1544: Note:
1545: We are using a first order FEM model for the weak form\:
1547: $$
1548: \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
1549: + \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
1550: $$
1552: .seealso: `PetscDS`, `PetscDSGetJacobian()`, `PetscPointJacFn`
1553: @*/
1554: PetscErrorCode PetscDSSetJacobian(PetscDS ds, PetscInt f, PetscInt g, PetscPointJacFn *g0, PetscPointJacFn *g1, PetscPointJacFn *g2, PetscPointJacFn *g3)
1555: {
1556: PetscFunctionBegin;
1562: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1563: PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
1564: PetscCall(PetscWeakFormSetIndexJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
1565: PetscFunctionReturn(PETSC_SUCCESS);
1566: }
1568: /*@
1569: PetscDSUseJacobianPreconditioner - Set whether to construct a Jacobian preconditioner
1571: Not Collective
1573: Input Parameters:
1574: + prob - The `PetscDS`
1575: - useJacPre - flag that enables construction of a Jacobian preconditioner
1577: Level: intermediate
1579: Developer Note:
1580: Should be called `PetscDSSetUseJacobianPreconditioner()`
1582: .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`
1583: @*/
1584: PetscErrorCode PetscDSUseJacobianPreconditioner(PetscDS prob, PetscBool useJacPre)
1585: {
1586: PetscFunctionBegin;
1588: prob->useJacPre = useJacPre;
1589: PetscFunctionReturn(PETSC_SUCCESS);
1590: }
1592: /*@
1593: PetscDSHasJacobianPreconditioner - Checks if a Jacobian matrix for constructing a preconditioner has been set
1595: Not Collective
1597: Input Parameter:
1598: . ds - The `PetscDS`
1600: Output Parameter:
1601: . hasJacPre - the flag
1603: Level: intermediate
1605: .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`
1606: @*/
1607: PetscErrorCode PetscDSHasJacobianPreconditioner(PetscDS ds, PetscBool *hasJacPre)
1608: {
1609: PetscFunctionBegin;
1611: *hasJacPre = PETSC_FALSE;
1612: if (!ds->useJacPre) PetscFunctionReturn(PETSC_SUCCESS);
1613: PetscCall(PetscWeakFormHasJacobianPreconditioner(ds->wf, hasJacPre));
1614: PetscFunctionReturn(PETSC_SUCCESS);
1615: }
1617: /*@C
1618: PetscDSGetJacobianPreconditioner - Get the pointwise Jacobian function for given test and basis field that constructs the matrix used
1619: to compute the preconditioner. If this is missing, the system matrix is used to build the preconditioner.
1621: Not Collective
1623: Input Parameters:
1624: + ds - The `PetscDS`
1625: . f - The test field number
1626: - g - The field number
1628: Output Parameters:
1629: + g0 - integrand for the test and basis function term, see `PetscPointJacFn`
1630: . g1 - integrand for the test function and basis function gradient term, see `PetscPointJacFn`
1631: . g2 - integrand for the test function gradient and basis function term, see `PetscPointJacFn`
1632: - g3 - integrand for the test function gradient and basis function gradient term, see `PetscPointJacFn`
1634: Level: intermediate
1636: Note:
1637: We are using a first order FEM model for the weak form\:
1639: $$
1640: \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
1641: + \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
1642: $$
1644: Developer Note:
1645: The name is confusing since the function computes a matrix used to construct the preconditioner, not a preconditioner.
1647: .seealso: `PetscDS`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`, `PetscPointJacFn`
1648: @*/
1649: PetscErrorCode PetscDSGetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, PetscPointJacFn **g0, PetscPointJacFn **g1, PetscPointJacFn **g2, PetscPointJacFn **g3)
1650: {
1651: PetscPointJacFn **tmp0, **tmp1, **tmp2, **tmp3;
1652: PetscInt n0, n1, n2, n3;
1654: PetscFunctionBegin;
1656: 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);
1657: 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);
1658: PetscCall(PetscWeakFormGetJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
1659: *g0 = tmp0 ? tmp0[0] : NULL;
1660: *g1 = tmp1 ? tmp1[0] : NULL;
1661: *g2 = tmp2 ? tmp2[0] : NULL;
1662: *g3 = tmp3 ? tmp3[0] : NULL;
1663: PetscFunctionReturn(PETSC_SUCCESS);
1664: }
1666: /*@C
1667: PetscDSSetJacobianPreconditioner - Set the pointwise Jacobian function for given test and basis fields that constructs the matrix used
1668: to compute the preconditioner. If this is missing, the system matrix is used to build the preconditioner.
1670: Not Collective
1672: Input Parameters:
1673: + ds - The `PetscDS`
1674: . f - The test field number
1675: . g - The field number
1676: . g0 - integrand for the test and basis function term, see `PetscPointJacFn`
1677: . g1 - integrand for the test function and basis function gradient term, see `PetscPointJacFn`
1678: . g2 - integrand for the test function gradient and basis function term, see `PetscPointJacFn`
1679: - g3 - integrand for the test function gradient and basis function gradient term, see `PetscPointJacFn`
1681: Level: intermediate
1683: Note:
1684: We are using a first order FEM model for the weak form\:
1686: $$
1687: \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
1688: + \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
1689: $$
1691: Developer Note:
1692: The name is confusing since the function computes a matrix used to construct the preconditioner, not a preconditioner.
1694: .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobian()`, `PetscPointJacFn`
1695: @*/
1696: PetscErrorCode PetscDSSetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, PetscPointJacFn *g0, PetscPointJacFn *g1, PetscPointJacFn *g2, PetscPointJacFn *g3)
1697: {
1698: PetscFunctionBegin;
1704: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1705: PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
1706: PetscCall(PetscWeakFormSetIndexJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
1707: PetscFunctionReturn(PETSC_SUCCESS);
1708: }
1710: /*@
1711: PetscDSHasDynamicJacobian - Signals that a dynamic Jacobian, $dF/du_t$, has been set
1713: Not Collective
1715: Input Parameter:
1716: . ds - The `PetscDS`
1718: Output Parameter:
1719: . hasDynJac - flag that pointwise function for dynamic Jacobian has been set
1721: Level: intermediate
1723: .seealso: `PetscDS`, `PetscDSGetDynamicJacobian()`, `PetscDSSetDynamicJacobian()`, `PetscDSGetJacobian()`
1724: @*/
1725: PetscErrorCode PetscDSHasDynamicJacobian(PetscDS ds, PetscBool *hasDynJac)
1726: {
1727: PetscFunctionBegin;
1729: PetscCall(PetscWeakFormHasDynamicJacobian(ds->wf, hasDynJac));
1730: PetscFunctionReturn(PETSC_SUCCESS);
1731: }
1733: /*@C
1734: PetscDSGetDynamicJacobian - Get the pointwise dynamic Jacobian, $dF/du_t$, function for given test and basis field
1736: Not Collective
1738: Input Parameters:
1739: + ds - The `PetscDS`
1740: . f - The test field number
1741: - g - The field number
1743: Output Parameters:
1744: + g0 - integrand for the test and basis function term, see `PetscPointJacFn`
1745: . g1 - integrand for the test function and basis function gradient term, see `PetscPointJacFn`
1746: . g2 - integrand for the test function gradient and basis function term, see `PetscPointJacFn`
1747: - g3 - integrand for the test function gradient and basis function gradient term, see `PetscPointJacFn`
1749: Level: intermediate
1751: Note:
1752: We are using a first order FEM model for the weak form\:
1754: $$
1755: \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
1756: + \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
1757: $$
1759: .seealso: `PetscDS`, `PetscDSSetJacobian()`, `PetscDSSetDynamicJacobian()`, `PetscPointJacFn`
1760: @*/
1761: PetscErrorCode PetscDSGetDynamicJacobian(PetscDS ds, PetscInt f, PetscInt g, PetscPointJacFn **g0, PetscPointJacFn **g1, PetscPointJacFn **g2, PetscPointJacFn **g3)
1762: {
1763: PetscPointJacFn **tmp0, **tmp1, **tmp2, **tmp3;
1764: PetscInt n0, n1, n2, n3;
1766: PetscFunctionBegin;
1768: 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);
1769: 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);
1770: PetscCall(PetscWeakFormGetDynamicJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
1771: *g0 = tmp0 ? tmp0[0] : NULL;
1772: *g1 = tmp1 ? tmp1[0] : NULL;
1773: *g2 = tmp2 ? tmp2[0] : NULL;
1774: *g3 = tmp3 ? tmp3[0] : NULL;
1775: PetscFunctionReturn(PETSC_SUCCESS);
1776: }
1778: /*@C
1779: PetscDSSetDynamicJacobian - Set the pointwise dynamic Jacobian, $dF/du_t$, function for given test and basis fields
1781: Not Collective
1783: Input Parameters:
1784: + ds - The `PetscDS`
1785: . f - The test field number
1786: . g - The field number
1787: . g0 - integrand for the test and basis function term, see `PetscPointJacFn`
1788: . g1 - integrand for the test function and basis function gradient term, see `PetscPointJacFn`
1789: . g2 - integrand for the test function gradient and basis function term, see `PetscPointJacFn`
1790: - g3 - integrand for the test function gradient and basis function gradient term, see `PetscPointJacFn`
1792: Level: intermediate
1794: Note:
1795: We are using a first order FEM model for the weak form\:
1797: $$
1798: \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
1799: + \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
1800: $$
1802: .seealso: `PetscDS`, `PetscDSGetDynamicJacobian()`, `PetscDSGetJacobian()`, `PetscPointJacFn`
1803: @*/
1804: PetscErrorCode PetscDSSetDynamicJacobian(PetscDS ds, PetscInt f, PetscInt g, PetscPointJacFn *g0, PetscPointJacFn *g1, PetscPointJacFn *g2, PetscPointJacFn *g3)
1805: {
1806: PetscFunctionBegin;
1812: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1813: PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
1814: PetscCall(PetscWeakFormSetIndexDynamicJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
1815: PetscFunctionReturn(PETSC_SUCCESS);
1816: }
1818: /*@C
1819: PetscDSGetRiemannSolver - Returns the Riemann solver for the given field
1821: Not Collective
1823: Input Parameters:
1824: + ds - The `PetscDS` object
1825: - f - The field number
1827: Output Parameter:
1828: . r - Riemann solver, see `PetscRiemannFn`
1830: Level: intermediate
1832: .seealso: `PetscDS`, `PetscRiemannFn`, `PetscDSSetRiemannSolver()`
1833: @*/
1834: PetscErrorCode PetscDSGetRiemannSolver(PetscDS ds, PetscInt f, PetscRiemannFn **r)
1835: {
1836: PetscRiemannFn **tmp;
1837: PetscInt n;
1839: PetscFunctionBegin;
1841: PetscAssertPointer(r, 3);
1842: 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);
1843: PetscCall(PetscWeakFormGetRiemannSolver(ds->wf, NULL, 0, f, 0, &n, &tmp));
1844: *r = tmp ? tmp[0] : NULL;
1845: PetscFunctionReturn(PETSC_SUCCESS);
1846: }
1848: /*@C
1849: PetscDSSetRiemannSolver - Sets the Riemann solver for the given field
1851: Not Collective
1853: Input Parameters:
1854: + ds - The `PetscDS` object
1855: . f - The field number
1856: - r - Riemann solver, see `PetscRiemannFn`
1858: Level: intermediate
1860: .seealso: `PetscDS`, `PetscRiemannFn`, `PetscDSGetRiemannSolver()`
1861: @*/
1862: PetscErrorCode PetscDSSetRiemannSolver(PetscDS ds, PetscInt f, PetscRiemannFn *r)
1863: {
1864: PetscFunctionBegin;
1867: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1868: PetscCall(PetscWeakFormSetIndexRiemannSolver(ds->wf, NULL, 0, f, 0, 0, r));
1869: PetscFunctionReturn(PETSC_SUCCESS);
1870: }
1872: /*@C
1873: PetscDSGetUpdate - Get the pointwise update function for a given field
1875: Not Collective
1877: Input Parameters:
1878: + ds - The `PetscDS`
1879: - f - The field number
1881: Output Parameter:
1882: . update - update function, see `PetscPointFn`
1884: Level: intermediate
1886: .seealso: `PetscDS`, `PetscPointFn`, `PetscDSSetUpdate()`, `PetscDSSetResidual()`
1887: @*/
1888: PetscErrorCode PetscDSGetUpdate(PetscDS ds, PetscInt f, PetscPointFn **update)
1889: {
1890: PetscFunctionBegin;
1892: 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);
1893: if (update) {
1894: PetscAssertPointer(update, 3);
1895: *update = ds->update[f];
1896: }
1897: PetscFunctionReturn(PETSC_SUCCESS);
1898: }
1900: /*@C
1901: PetscDSSetUpdate - Set the pointwise update function for a given field
1903: Not Collective
1905: Input Parameters:
1906: + ds - The `PetscDS`
1907: . f - The field number
1908: - update - update function, see `PetscPointFn`
1910: Level: intermediate
1912: .seealso: `PetscDS`, `PetscPointFn`, `PetscDSGetResidual()`
1913: @*/
1914: PetscErrorCode PetscDSSetUpdate(PetscDS ds, PetscInt f, PetscPointFn *update)
1915: {
1916: PetscFunctionBegin;
1919: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1920: PetscCall(PetscDSEnlarge_Static(ds, f + 1));
1921: ds->update[f] = update;
1922: PetscFunctionReturn(PETSC_SUCCESS);
1923: }
1925: /*@C
1926: PetscDSGetContext - Returns the context that was passed by `PetscDSSetContext()`
1928: Not Collective
1930: Input Parameters:
1931: + ds - The `PetscDS`
1932: . f - The field number
1933: - ctx - the context
1935: Level: intermediate
1937: Fortran Notes:
1938: This only works when the context is a Fortran derived type or a `PetscObject`. Define `ctx` with
1939: .vb
1940: type(tUsertype), pointer :: ctx
1941: .ve
1943: .seealso: `PetscDS`, `PetscPointFn`, `PetscDSSetContext()`
1944: @*/
1945: PetscErrorCode PetscDSGetContext(PetscDS ds, PetscInt f, PetscCtxRt ctx)
1946: {
1947: PetscFunctionBegin;
1949: 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);
1950: PetscAssertPointer(ctx, 3);
1951: *(void **)ctx = ds->ctx[f];
1952: PetscFunctionReturn(PETSC_SUCCESS);
1953: }
1955: /*@C
1956: PetscDSSetContext - Sets the context that is passed back to some of the pointwise function callbacks used by this `PetscDS`
1958: Not Collective
1960: Input Parameters:
1961: + ds - The `PetscDS`
1962: . f - The field number
1963: - ctx - the context
1965: Level: intermediate
1967: .seealso: `PetscDS`, `PetscPointFn`, `PetscDSGetContext()`
1968: @*/
1969: PetscErrorCode PetscDSSetContext(PetscDS ds, PetscInt f, PetscCtx ctx)
1970: {
1971: PetscFunctionBegin;
1973: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
1974: PetscCall(PetscDSEnlarge_Static(ds, f + 1));
1975: ds->ctx[f] = ctx;
1976: PetscFunctionReturn(PETSC_SUCCESS);
1977: }
1979: /*@C
1980: PetscDSGetBdResidual - Get the pointwise boundary residual function for a given test field
1982: Not Collective
1984: Input Parameters:
1985: + ds - The PetscDS
1986: - f - The test field number
1988: Output Parameters:
1989: + f0 - boundary integrand for the test function term, see `PetscBdPointFn`
1990: - f1 - boundary integrand for the test function gradient term, see `PetscBdPointFn`
1992: Level: intermediate
1994: Note:
1995: We are using a first order FEM model for the weak form\:
1997: $$
1998: \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
1999: $$
2001: .seealso: `PetscDS`, `PetscBdPointFn`, `PetscDSSetBdResidual()`
2002: @*/
2003: PetscErrorCode PetscDSGetBdResidual(PetscDS ds, PetscInt f, PetscBdPointFn **f0, PetscBdPointFn **f1)
2004: {
2005: PetscBdPointFn **tmp0, **tmp1;
2006: PetscInt n0, n1;
2008: PetscFunctionBegin;
2010: 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);
2011: PetscCall(PetscWeakFormGetBdResidual(ds->wf, NULL, 0, f, 0, &n0, &tmp0, &n1, &tmp1));
2012: *f0 = tmp0 ? tmp0[0] : NULL;
2013: *f1 = tmp1 ? tmp1[0] : NULL;
2014: PetscFunctionReturn(PETSC_SUCCESS);
2015: }
2017: /*@C
2018: PetscDSSetBdResidual - Get the pointwise boundary residual function for a given test field
2020: Not Collective
2022: Input Parameters:
2023: + ds - The `PetscDS`
2024: . f - The test field number
2025: . f0 - boundary integrand for the test function term, see `PetscBdPointFn`
2026: - f1 - boundary integrand for the test function gradient term, see `PetscBdPointFn`
2028: Level: intermediate
2030: Note:
2031: We are using a first order FEM model for the weak form\:
2033: $$
2034: \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
2035: $$
2037: .seealso: `PetscDS`, `PetscBdPointFn`, `PetscDSGetBdResidual()`
2038: @*/
2039: PetscErrorCode PetscDSSetBdResidual(PetscDS ds, PetscInt f, PetscBdPointFn *f0, PetscBdPointFn *f1)
2040: {
2041: PetscFunctionBegin;
2043: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2044: PetscCall(PetscWeakFormSetIndexBdResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1));
2045: PetscFunctionReturn(PETSC_SUCCESS);
2046: }
2048: /*@
2049: PetscDSHasBdJacobian - Indicates that boundary Jacobian functions have been set
2051: Not Collective
2053: Input Parameter:
2054: . ds - The `PetscDS`
2056: Output Parameter:
2057: . hasBdJac - flag that pointwise function for the boundary Jacobian has been set
2059: Level: intermediate
2061: .seealso: `PetscDS`, `PetscDSHasJacobian()`, `PetscDSSetBdJacobian()`, `PetscDSGetBdJacobian()`
2062: @*/
2063: PetscErrorCode PetscDSHasBdJacobian(PetscDS ds, PetscBool *hasBdJac)
2064: {
2065: PetscFunctionBegin;
2067: PetscAssertPointer(hasBdJac, 2);
2068: PetscCall(PetscWeakFormHasBdJacobian(ds->wf, hasBdJac));
2069: PetscFunctionReturn(PETSC_SUCCESS);
2070: }
2072: /*@C
2073: PetscDSGetBdJacobian - Get the pointwise boundary Jacobian function for given test and basis field
2075: Not Collective
2077: Input Parameters:
2078: + ds - The `PetscDS`
2079: . f - The test field number
2080: - g - The field number
2082: Output Parameters:
2083: + g0 - integrand for the test and basis function term, see `PetscBdPointJacFn`
2084: . g1 - integrand for the test function and basis function gradient term, see `PetscBdPointJacFn`
2085: . g2 - integrand for the test function gradient and basis function term, see `PetscBdPointJacFn`
2086: - g3 - integrand for the test function gradient and basis function gradient term, see `PetscBdPointJacFn`
2088: Level: intermediate
2090: Note:
2091: We are using a first order FEM model for the weak form\:
2093: $$
2094: \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
2095: + \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
2096: $$
2098: .seealso: `PetscDS`, `PetscBdPointJacFn`, `PetscDSSetBdJacobian()`
2099: @*/
2100: PetscErrorCode PetscDSGetBdJacobian(PetscDS ds, PetscInt f, PetscInt g, PetscBdPointJacFn **g0, PetscBdPointJacFn **g1, PetscBdPointJacFn **g2, PetscBdPointJacFn **g3)
2101: {
2102: PetscBdPointJacFn **tmp0, **tmp1, **tmp2, **tmp3;
2103: PetscInt n0, n1, n2, n3;
2105: PetscFunctionBegin;
2107: 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);
2108: 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);
2109: PetscCall(PetscWeakFormGetBdJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
2110: *g0 = tmp0 ? tmp0[0] : NULL;
2111: *g1 = tmp1 ? tmp1[0] : NULL;
2112: *g2 = tmp2 ? tmp2[0] : NULL;
2113: *g3 = tmp3 ? tmp3[0] : NULL;
2114: PetscFunctionReturn(PETSC_SUCCESS);
2115: }
2117: /*@C
2118: PetscDSSetBdJacobian - Set the pointwise boundary Jacobian function for given test and basis field
2120: Not Collective
2122: Input Parameters:
2123: + ds - The PetscDS
2124: . f - The test field number
2125: . g - The field number
2126: . g0 - integrand for the test and basis function term, see `PetscBdPointJacFn`
2127: . g1 - integrand for the test function and basis function gradient term, see `PetscBdPointJacFn`
2128: . g2 - integrand for the test function gradient and basis function term, see `PetscBdPointJacFn`
2129: - g3 - integrand for the test function gradient and basis function gradient term, see `PetscBdPointJacFn`
2131: Level: intermediate
2133: Note:
2134: We are using a first order FEM model for the weak form\:
2136: $$
2137: \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
2138: + \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
2139: $$
2141: .seealso: `PetscDS`, `PetscBdPointJacFn`, `PetscDSGetBdJacobian()`
2142: @*/
2143: PetscErrorCode PetscDSSetBdJacobian(PetscDS ds, PetscInt f, PetscInt g, PetscBdPointJacFn *g0, PetscBdPointJacFn *g1, PetscBdPointJacFn *g2, PetscBdPointJacFn *g3)
2144: {
2145: PetscFunctionBegin;
2151: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2152: PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
2153: PetscCall(PetscWeakFormSetIndexBdJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
2154: PetscFunctionReturn(PETSC_SUCCESS);
2155: }
2157: /*@
2158: PetscDSHasBdJacobianPreconditioner - Signals that boundary Jacobian preconditioner functions have been set with `PetscDSSetBdJacobianPreconditioner()`
2160: Not Collective
2162: Input Parameter:
2163: . ds - The `PetscDS`
2165: Output Parameter:
2166: . hasBdJacPre - flag that pointwise function for the boundary Jacobian matrix to construct the preconditioner has been set
2168: Level: intermediate
2170: Developer Note:
2171: The name is confusing since the function computes a matrix used to construct the preconditioner, not a preconditioner.
2173: .seealso: `PetscDS`, `PetscDSHasJacobian()`, `PetscDSSetBdJacobian()`, `PetscDSGetBdJacobian()`
2174: @*/
2175: PetscErrorCode PetscDSHasBdJacobianPreconditioner(PetscDS ds, PetscBool *hasBdJacPre)
2176: {
2177: PetscFunctionBegin;
2179: PetscAssertPointer(hasBdJacPre, 2);
2180: PetscCall(PetscWeakFormHasBdJacobianPreconditioner(ds->wf, hasBdJacPre));
2181: PetscFunctionReturn(PETSC_SUCCESS);
2182: }
2184: /*@C
2185: PetscDSGetBdJacobianPreconditioner - Get the pointwise boundary Jacobian function for given test and basis field that constructs the
2186: matrix used to construct the preconditioner
2188: Not Collective; No Fortran Support
2190: Input Parameters:
2191: + ds - The `PetscDS`
2192: . f - The test field number
2193: - g - The field number
2195: Output Parameters:
2196: + g0 - integrand for the test and basis function term, see `PetscBdPointJacFn`
2197: . g1 - integrand for the test function and basis function gradient term, see `PetscBdPointJacFn`
2198: . g2 - integrand for the test function gradient and basis function term, see `PetscBdPointJacFn`
2199: - g3 - integrand for the test function gradient and basis function gradient term, see `PetscBdPointJacFn`
2201: Level: intermediate
2203: Note:
2204: We are using a first order FEM model for the weak form\:
2206: $$
2207: \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
2208: + \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
2209: $$
2211: Developer Note:
2212: The name is confusing since the function computes a matrix used to construct the preconditioner, not a preconditioner.
2214: .seealso: `PetscDS`, `PetscBdPointJacFn`, `PetscDSSetBdJacobianPreconditioner()`
2215: @*/
2216: PetscErrorCode PetscDSGetBdJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, PetscBdPointJacFn **g0, PetscBdPointJacFn **g1, PetscBdPointJacFn **g2, PetscBdPointJacFn **g3)
2217: {
2218: PetscBdPointJacFn **tmp0, **tmp1, **tmp2, **tmp3;
2219: PetscInt n0, n1, n2, n3;
2221: PetscFunctionBegin;
2223: 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);
2224: 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);
2225: PetscCall(PetscWeakFormGetBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3));
2226: *g0 = tmp0 ? tmp0[0] : NULL;
2227: *g1 = tmp1 ? tmp1[0] : NULL;
2228: *g2 = tmp2 ? tmp2[0] : NULL;
2229: *g3 = tmp3 ? tmp3[0] : NULL;
2230: PetscFunctionReturn(PETSC_SUCCESS);
2231: }
2233: /*@C
2234: PetscDSSetBdJacobianPreconditioner - Set the pointwise boundary Jacobian preconditioner function for given test and basis field that constructs the
2235: matrix used to construct the preconditioner
2237: Not Collective; No Fortran Support
2239: Input Parameters:
2240: + ds - The `PetscDS`
2241: . f - The test field number
2242: . g - The field number
2243: . g0 - integrand for the test and basis function term, see `PetscBdPointJacFn`
2244: . g1 - integrand for the test function and basis function gradient term, see `PetscBdPointJacFn`
2245: . g2 - integrand for the test function gradient and basis function term, see `PetscBdPointJacFn`
2246: - g3 - integrand for the test function gradient and basis function gradient term, see `PetscBdPointJacFn`
2248: Level: intermediate
2250: Note:
2251: We are using a first order FEM model for the weak form\:
2253: $$
2254: \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
2255: + \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
2256: $$
2258: Developer Note:
2259: The name is confusing since the function computes a matrix used to construct the preconditioner, not a preconditioner.
2261: .seealso: `PetscDS`, `PetscBdPointJacFn`, `PetscDSGetBdJacobianPreconditioner()`
2262: @*/
2263: PetscErrorCode PetscDSSetBdJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, PetscBdPointJacFn *g0, PetscBdPointJacFn *g1, PetscBdPointJacFn *g2, PetscBdPointJacFn *g3)
2264: {
2265: PetscFunctionBegin;
2271: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2272: PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g);
2273: PetscCall(PetscWeakFormSetIndexBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3));
2274: PetscFunctionReturn(PETSC_SUCCESS);
2275: }
2277: /*@C
2278: PetscDSGetExactSolution - Get the pointwise exact solution function for a given test field
2280: Not Collective
2282: Input Parameters:
2283: + prob - The `PetscDS`
2284: - f - The test field number
2286: Output Parameters:
2287: + sol - exact solution function for the test field, see `PetscPointExactSolutionFn`
2288: - ctx - exact solution context
2290: Level: intermediate
2292: .seealso: `PetscDS`, `PetscPointExactSolutionFn`, `PetscDSSetExactSolution()`, `PetscDSGetExactSolutionTimeDerivative()`
2293: @*/
2294: PetscErrorCode PetscDSGetExactSolution(PetscDS prob, PetscInt f, PetscPointExactSolutionFn **sol, void **ctx)
2295: {
2296: PetscFunctionBegin;
2298: 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);
2299: if (sol) {
2300: PetscAssertPointer(sol, 3);
2301: *sol = prob->exactSol[f];
2302: }
2303: if (ctx) {
2304: PetscAssertPointer(ctx, 4);
2305: *ctx = prob->exactCtx[f];
2306: }
2307: PetscFunctionReturn(PETSC_SUCCESS);
2308: }
2310: /*@C
2311: PetscDSSetExactSolution - Set the pointwise exact solution function for a given test field
2313: Not Collective
2315: Input Parameters:
2316: + prob - The `PetscDS`
2317: . f - The test field number
2318: . sol - solution function for the test fields, see `PetscPointExactSolutionFn`
2319: - ctx - solution context or `NULL`
2321: Level: intermediate
2323: .seealso: `PetscDS`, `PetscPointExactSolutionFn`, `PetscDSGetExactSolution()`
2324: @*/
2325: PetscErrorCode PetscDSSetExactSolution(PetscDS prob, PetscInt f, PetscPointExactSolutionFn *sol, PetscCtx ctx)
2326: {
2327: PetscFunctionBegin;
2329: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2330: PetscCall(PetscDSEnlarge_Static(prob, f + 1));
2331: if (sol) {
2333: prob->exactSol[f] = sol;
2334: }
2335: if (ctx) {
2337: prob->exactCtx[f] = ctx;
2338: }
2339: PetscFunctionReturn(PETSC_SUCCESS);
2340: }
2342: /*@C
2343: PetscDSGetExactSolutionTimeDerivative - Get the pointwise time derivative of the exact solution function for a given test field
2345: Not Collective
2347: Input Parameters:
2348: + prob - The `PetscDS`
2349: - f - The test field number
2351: Output Parameters:
2352: + sol - time derivative of the exact solution for the test field, see `PetscPointExactSolutionFn`
2353: - ctx - the exact solution context
2355: Level: intermediate
2357: .seealso: `PetscDS`, `PetscPointExactSolutionFn`, `PetscDSSetExactSolutionTimeDerivative()`, `PetscDSGetExactSolution()`
2358: @*/
2359: PetscErrorCode PetscDSGetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscPointExactSolutionFn **sol, void **ctx)
2360: {
2361: PetscFunctionBegin;
2363: 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);
2364: if (sol) {
2365: PetscAssertPointer(sol, 3);
2366: *sol = prob->exactSol_t[f];
2367: }
2368: if (ctx) {
2369: PetscAssertPointer(ctx, 4);
2370: *ctx = prob->exactCtx_t[f];
2371: }
2372: PetscFunctionReturn(PETSC_SUCCESS);
2373: }
2375: /*@C
2376: PetscDSSetExactSolutionTimeDerivative - Set the pointwise time derivative of the exact solution function for a given test field
2378: Not Collective
2380: Input Parameters:
2381: + prob - The `PetscDS`
2382: . f - The test field number
2383: . sol - time derivative of the solution function for the test fields, see `PetscPointExactSolutionFn`
2384: - ctx - the solution context or `NULL`
2386: Level: intermediate
2388: .seealso: `PetscDS`, `PetscPointExactSolutionFn`, `PetscDSGetExactSolutionTimeDerivative()`, `PetscDSSetExactSolution()`
2389: @*/
2390: PetscErrorCode PetscDSSetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscPointExactSolutionFn *sol, PetscCtx ctx)
2391: {
2392: PetscFunctionBegin;
2394: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2395: PetscCall(PetscDSEnlarge_Static(prob, f + 1));
2396: if (sol) {
2398: prob->exactSol_t[f] = sol;
2399: }
2400: if (ctx) {
2402: prob->exactCtx_t[f] = ctx;
2403: }
2404: PetscFunctionReturn(PETSC_SUCCESS);
2405: }
2407: /*@C
2408: PetscDSGetLowerBound - Get the pointwise lower bound function for a given field
2410: Not Collective
2412: Input Parameters:
2413: + ds - The PetscDS
2414: - f - The field number
2416: Output Parameters:
2417: + lb - lower bound function for the field, see `PetscPointBoundFn`
2418: - ctx - lower bound context that was set with `PetscDSSetLowerBound()`
2420: Level: intermediate
2422: .seealso: `PetscDS`, `PetscPointBoundFn`, `PetscDSSetLowerBound()`, `PetscDSGetUpperBound()`, `PetscDSGetExactSolution()`
2423: @*/
2424: PetscErrorCode PetscDSGetLowerBound(PetscDS ds, PetscInt f, PetscPointBoundFn **lb, void **ctx)
2425: {
2426: PetscFunctionBegin;
2428: 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);
2429: if (lb) {
2430: PetscAssertPointer(lb, 3);
2431: *lb = ds->lowerBound[f];
2432: }
2433: if (ctx) {
2434: PetscAssertPointer(ctx, 4);
2435: *ctx = ds->lowerCtx[f];
2436: }
2437: PetscFunctionReturn(PETSC_SUCCESS);
2438: }
2440: /*@C
2441: PetscDSSetLowerBound - Set the pointwise lower bound function for a given field
2443: Not Collective
2445: Input Parameters:
2446: + ds - The `PetscDS`
2447: . f - The field number
2448: . lb - lower bound function for the test fields, see `PetscPointBoundFn`
2449: - ctx - lower bound context or `NULL` which will be passed to `lb`
2451: Level: intermediate
2453: .seealso: `PetscDS`, `PetscPointBoundFn`, `PetscDSGetLowerBound()`, `PetscDSGetUpperBound()`, `PetscDSGetExactSolution()`
2454: @*/
2455: PetscErrorCode PetscDSSetLowerBound(PetscDS ds, PetscInt f, PetscPointBoundFn *lb, PetscCtx ctx)
2456: {
2457: PetscFunctionBegin;
2459: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2460: PetscCall(PetscDSEnlarge_Static(ds, f + 1));
2461: if (lb) {
2463: ds->lowerBound[f] = lb;
2464: }
2465: if (ctx) {
2467: ds->lowerCtx[f] = ctx;
2468: }
2469: PetscFunctionReturn(PETSC_SUCCESS);
2470: }
2472: /*@C
2473: PetscDSGetUpperBound - Get the pointwise upper bound function for a given field
2475: Not Collective
2477: Input Parameters:
2478: + ds - The `PetscDS`
2479: - f - The field number
2481: Output Parameters:
2482: + ub - upper bound function for the field, see `PetscPointBoundFn`
2483: - ctx - upper bound context that was set with `PetscDSSetUpperBound()`
2485: Level: intermediate
2487: .seealso: `PetscDS`, `PetscPointBoundFn`, `PetscDSSetUpperBound()`, `PetscDSGetLowerBound()`, `PetscDSGetExactSolution()`
2488: @*/
2489: PetscErrorCode PetscDSGetUpperBound(PetscDS ds, PetscInt f, PetscPointBoundFn **ub, void **ctx)
2490: {
2491: PetscFunctionBegin;
2493: 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);
2494: if (ub) {
2495: PetscAssertPointer(ub, 3);
2496: *ub = ds->upperBound[f];
2497: }
2498: if (ctx) {
2499: PetscAssertPointer(ctx, 4);
2500: *ctx = ds->upperCtx[f];
2501: }
2502: PetscFunctionReturn(PETSC_SUCCESS);
2503: }
2505: /*@C
2506: PetscDSSetUpperBound - Set the pointwise upper bound function for a given field
2508: Not Collective
2510: Input Parameters:
2511: + ds - The `PetscDS`
2512: . f - The field number
2513: . ub - upper bound function for the test fields, see `PetscPointBoundFn`
2514: - ctx - context or `NULL` that will be passed to `ub`
2516: Level: intermediate
2518: .seealso: `PetscDS`, `PetscPointBoundFn`, `PetscDSGetUpperBound()`, `PetscDSGetLowerBound()`, `PetscDSGetExactSolution()`
2519: @*/
2520: PetscErrorCode PetscDSSetUpperBound(PetscDS ds, PetscInt f, PetscPointBoundFn *ub, PetscCtx ctx)
2521: {
2522: PetscFunctionBegin;
2524: PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f);
2525: PetscCall(PetscDSEnlarge_Static(ds, f + 1));
2526: if (ub) {
2528: ds->upperBound[f] = ub;
2529: }
2530: if (ctx) {
2532: ds->upperCtx[f] = ctx;
2533: }
2534: PetscFunctionReturn(PETSC_SUCCESS);
2535: }
2537: /*@C
2538: PetscDSGetConstants - Returns the array of constants passed to point functions from a `PetscDS` object
2540: Not Collective
2542: Input Parameter:
2543: . ds - The `PetscDS` object
2545: Output Parameters:
2546: + numConstants - The number of constants, or pass in `NULL` if not required
2547: - constants - The array of constants, `NULL` if there are none
2549: Level: intermediate
2551: .seealso: `PetscDS`, `PetscDSSetConstants()`, `PetscDSCreate()`
2552: @*/
2553: PetscErrorCode PetscDSGetConstants(PetscDS ds, PeOp PetscInt *numConstants, PeOp const PetscScalar *constants[])
2554: {
2555: PetscFunctionBegin;
2557: if (numConstants) {
2558: PetscAssertPointer(numConstants, 2);
2559: *numConstants = ds->numConstants;
2560: }
2561: if (constants) {
2562: PetscAssertPointer(constants, 3);
2563: *constants = ds->constants;
2564: }
2565: PetscFunctionReturn(PETSC_SUCCESS);
2566: }
2568: /*@C
2569: PetscDSSetConstants - Set the array of constants passed to point functions from a `PetscDS`
2571: Not Collective
2573: Input Parameters:
2574: + ds - The `PetscDS` object
2575: . numConstants - The number of constants
2576: - constants - The array of constants, `NULL` if there are none
2578: Level: intermediate
2580: .seealso: `PetscDS`, `PetscDSGetConstants()`, `PetscDSCreate()`
2581: @*/
2582: PetscErrorCode PetscDSSetConstants(PetscDS ds, PetscInt numConstants, PetscScalar constants[])
2583: {
2584: PetscFunctionBegin;
2586: if (numConstants != ds->numConstants) {
2587: PetscCall(PetscFree(ds->constants));
2588: ds->numConstants = numConstants;
2589: PetscCall(PetscMalloc1(ds->numConstants + ds->numFuncConstants, &ds->constants));
2590: }
2591: if (ds->numConstants) {
2592: PetscAssertPointer(constants, 3);
2593: PetscCall(PetscArraycpy(ds->constants, constants, ds->numConstants));
2594: }
2595: PetscFunctionReturn(PETSC_SUCCESS);
2596: }
2598: /*@C
2599: PetscDSSetIntegrationParameters - Set the parameters for a particular integration
2601: Not Collective
2603: Input Parameters:
2604: + ds - The `PetscDS` object
2605: . fieldI - The test field for a given point function, or `PETSC_DETERMINE`
2606: - fieldJ - The basis field for a given point function, or `PETSC_DETERMINE`
2608: Level: intermediate
2610: .seealso: `PetscDS`, `PetscDSSetConstants()`, `PetscDSGetConstants()`, `PetscDSCreate()`
2611: @*/
2612: PetscErrorCode PetscDSSetIntegrationParameters(PetscDS ds, PetscInt fieldI, PetscInt fieldJ)
2613: {
2614: PetscFunctionBegin;
2616: ds->constants[ds->numConstants] = fieldI;
2617: ds->constants[ds->numConstants + 1] = fieldJ;
2618: PetscFunctionReturn(PETSC_SUCCESS);
2619: }
2621: /*@C
2622: PetscDSSetCellParameters - Set the parameters for a particular cell
2624: Not Collective
2626: Input Parameters:
2627: + ds - The `PetscDS` object
2628: - volume - The cell volume
2630: Level: intermediate
2632: .seealso: `PetscDS`, `PetscDSSetConstants()`, `PetscDSGetConstants()`, `PetscDSCreate()`
2633: @*/
2634: PetscErrorCode PetscDSSetCellParameters(PetscDS ds, PetscReal volume)
2635: {
2636: PetscFunctionBegin;
2638: ds->constants[ds->numConstants + 2] = volume;
2639: PetscFunctionReturn(PETSC_SUCCESS);
2640: }
2642: /*@
2643: PetscDSGetFieldIndex - Returns the index of the given field
2645: Not Collective
2647: Input Parameters:
2648: + prob - The `PetscDS` object
2649: - disc - The discretization object
2651: Output Parameter:
2652: . f - The field number
2654: Level: beginner
2656: .seealso: `PetscDS`, `PetscGetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2657: @*/
2658: PetscErrorCode PetscDSGetFieldIndex(PetscDS prob, PetscObject disc, PetscInt *f)
2659: {
2660: PetscInt g;
2662: PetscFunctionBegin;
2664: PetscAssertPointer(f, 3);
2665: *f = -1;
2666: for (g = 0; g < prob->Nf; ++g) {
2667: if (disc == prob->disc[g]) break;
2668: }
2669: PetscCheck(g != prob->Nf, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Field not found in PetscDS.");
2670: *f = g;
2671: PetscFunctionReturn(PETSC_SUCCESS);
2672: }
2674: /*@
2675: PetscDSGetFieldSize - Returns the size of the given field in the full space basis
2677: Not Collective
2679: Input Parameters:
2680: + prob - The `PetscDS` object
2681: - f - The field number
2683: Output Parameter:
2684: . size - The size
2686: Level: beginner
2688: .seealso: `PetscDS`, `PetscDSGetFieldOffset()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2689: @*/
2690: PetscErrorCode PetscDSGetFieldSize(PetscDS prob, PetscInt f, PetscInt *size)
2691: {
2692: PetscFunctionBegin;
2694: PetscAssertPointer(size, 3);
2695: 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);
2696: PetscCall(PetscDSSetUp(prob));
2697: *size = prob->Nb[f];
2698: PetscFunctionReturn(PETSC_SUCCESS);
2699: }
2701: /*@
2702: PetscDSGetFieldOffset - Returns the offset of the given field in the full space basis
2704: Not Collective
2706: Input Parameters:
2707: + prob - The `PetscDS` object
2708: - f - The field number
2710: Output Parameter:
2711: . off - The offset
2713: Level: beginner
2715: .seealso: `PetscDS`, `PetscDSGetFieldSize()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2716: @*/
2717: PetscErrorCode PetscDSGetFieldOffset(PetscDS prob, PetscInt f, PetscInt *off)
2718: {
2719: PetscInt size, g;
2721: PetscFunctionBegin;
2723: PetscAssertPointer(off, 3);
2724: 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);
2725: *off = 0;
2726: for (g = 0; g < f; ++g) {
2727: PetscCall(PetscDSGetFieldSize(prob, g, &size));
2728: *off += size;
2729: }
2730: PetscFunctionReturn(PETSC_SUCCESS);
2731: }
2733: /*@
2734: PetscDSGetFieldOffsetCohesive - Returns the offset of the given field in the full space basis on a cohesive cell
2736: Not Collective
2738: Input Parameters:
2739: + ds - The `PetscDS` object
2740: - f - The field number
2742: Output Parameter:
2743: . off - The offset
2745: Level: beginner
2747: .seealso: `PetscDS`, `PetscDSGetFieldSize()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2748: @*/
2749: PetscErrorCode PetscDSGetFieldOffsetCohesive(PetscDS ds, PetscInt f, PetscInt *off)
2750: {
2751: PetscInt size, g;
2753: PetscFunctionBegin;
2755: PetscAssertPointer(off, 3);
2756: 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);
2757: *off = 0;
2758: for (g = 0; g < f; ++g) {
2759: PetscBool cohesive;
2761: PetscCall(PetscDSGetCohesive(ds, g, &cohesive));
2762: PetscCall(PetscDSGetFieldSize(ds, g, &size));
2763: *off += cohesive ? size : size * 2;
2764: }
2765: PetscFunctionReturn(PETSC_SUCCESS);
2766: }
2768: /*@
2769: PetscDSGetDimensions - Returns the size of the approximation space for each field on an evaluation point
2771: Not Collective
2773: Input Parameter:
2774: . prob - The `PetscDS` object
2776: Output Parameter:
2777: . dimensions - The number of dimensions
2779: Level: beginner
2781: .seealso: `PetscDS`, `PetscDSGetComponentOffsets()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2782: @*/
2783: PetscErrorCode PetscDSGetDimensions(PetscDS prob, PetscInt *dimensions[])
2784: {
2785: PetscFunctionBegin;
2787: PetscCall(PetscDSSetUp(prob));
2788: PetscAssertPointer(dimensions, 2);
2789: *dimensions = prob->Nb;
2790: PetscFunctionReturn(PETSC_SUCCESS);
2791: }
2793: /*@
2794: PetscDSGetComponents - Returns the number of components for each field on an evaluation point
2796: Not Collective
2798: Input Parameter:
2799: . prob - The `PetscDS` object
2801: Output Parameter:
2802: . components - The number of components
2804: Level: beginner
2806: .seealso: `PetscDS`, `PetscDSGetComponentOffsets()`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2807: @*/
2808: PetscErrorCode PetscDSGetComponents(PetscDS prob, PetscInt *components[])
2809: {
2810: PetscFunctionBegin;
2812: PetscCall(PetscDSSetUp(prob));
2813: PetscAssertPointer(components, 2);
2814: *components = prob->Nc;
2815: PetscFunctionReturn(PETSC_SUCCESS);
2816: }
2818: /*@
2819: PetscDSGetComponentOffset - Returns the offset of the given field on an evaluation point
2821: Not Collective
2823: Input Parameters:
2824: + prob - The `PetscDS` object
2825: - f - The field number
2827: Output Parameter:
2828: . off - The offset
2830: Level: beginner
2832: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2833: @*/
2834: PetscErrorCode PetscDSGetComponentOffset(PetscDS prob, PetscInt f, PetscInt *off)
2835: {
2836: PetscFunctionBegin;
2838: PetscAssertPointer(off, 3);
2839: 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);
2840: PetscCall(PetscDSSetUp(prob));
2841: *off = prob->off[f];
2842: PetscFunctionReturn(PETSC_SUCCESS);
2843: }
2845: /*@
2846: PetscDSGetComponentOffsets - Returns the offset of each field on an evaluation point
2848: Not Collective
2850: Input Parameter:
2851: . prob - The `PetscDS` object
2853: Output Parameter:
2854: . offsets - The offsets
2856: Level: beginner
2858: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2859: @*/
2860: PetscErrorCode PetscDSGetComponentOffsets(PetscDS prob, PetscInt *offsets[])
2861: {
2862: PetscFunctionBegin;
2864: PetscAssertPointer(offsets, 2);
2865: PetscCall(PetscDSSetUp(prob));
2866: *offsets = prob->off;
2867: PetscFunctionReturn(PETSC_SUCCESS);
2868: }
2870: /*@
2871: PetscDSGetComponentDerivativeOffsets - Returns the offset of each field derivative on an evaluation point
2873: Not Collective
2875: Input Parameter:
2876: . prob - The `PetscDS` object
2878: Output Parameter:
2879: . offsets - The offsets
2881: Level: beginner
2883: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2884: @*/
2885: PetscErrorCode PetscDSGetComponentDerivativeOffsets(PetscDS prob, PetscInt *offsets[])
2886: {
2887: PetscFunctionBegin;
2889: PetscAssertPointer(offsets, 2);
2890: PetscCall(PetscDSSetUp(prob));
2891: *offsets = prob->offDer;
2892: PetscFunctionReturn(PETSC_SUCCESS);
2893: }
2895: /*@
2896: PetscDSGetComponentOffsetsCohesive - Returns the offset of each field on an evaluation point
2898: Not Collective
2900: Input Parameters:
2901: + ds - The `PetscDS` object
2902: - s - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive
2904: Output Parameter:
2905: . offsets - The offsets
2907: Level: beginner
2909: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2910: @*/
2911: PetscErrorCode PetscDSGetComponentOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[])
2912: {
2913: PetscFunctionBegin;
2915: PetscAssertPointer(offsets, 3);
2916: PetscCheck(ds->isCohesive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cohesive offsets are only valid for a cohesive DS");
2917: PetscCheck(!(s < 0) && !(s > 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cohesive side %" PetscInt_FMT " is not in [0, 2]", s);
2918: PetscCall(PetscDSSetUp(ds));
2919: *offsets = ds->offCohesive[s];
2920: PetscFunctionReturn(PETSC_SUCCESS);
2921: }
2923: /*@
2924: PetscDSGetComponentDerivativeOffsetsCohesive - Returns the offset of each field derivative on an evaluation point
2926: Not Collective
2928: Input Parameters:
2929: + ds - The `PetscDS` object
2930: - s - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive
2932: Output Parameter:
2933: . offsets - The offsets
2935: Level: beginner
2937: .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()`
2938: @*/
2939: PetscErrorCode PetscDSGetComponentDerivativeOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[])
2940: {
2941: PetscFunctionBegin;
2943: PetscAssertPointer(offsets, 3);
2944: PetscCheck(ds->isCohesive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cohesive offsets are only valid for a cohesive DS");
2945: PetscCheck(!(s < 0) && !(s > 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cohesive side %" PetscInt_FMT " is not in [0, 2]", s);
2946: PetscCall(PetscDSSetUp(ds));
2947: *offsets = ds->offDerCohesive[s];
2948: PetscFunctionReturn(PETSC_SUCCESS);
2949: }
2951: /*@C
2952: PetscDSGetTabulation - Return the basis tabulation at quadrature points for the volume discretization
2954: Not Collective
2956: Input Parameter:
2957: . prob - The `PetscDS` object
2959: Output Parameter:
2960: . T - The basis function and derivatives tabulation at quadrature points for each field, see `PetscTabulation` for its details
2962: Level: intermediate
2964: Note:
2965: The tabulation is only valid so long as the `PetscDS` has not be destroyed. There is no `PetscDSRestoreTabulation()` in C.
2967: Fortran Note:
2968: Use the declaration
2969: .vb
2970: PetscTabulation, pointer :: tab(:)
2971: .ve
2972: and access the values using, for example,
2973: .vb
2974: tab(i)%ptr%K
2975: tab(i)%ptr%T(j)%ptr
2976: .ve
2977: where $ i = 1, 2, ..., Nf $ and $ j = 1, 2, ..., tab(i)%ptr%K+1 $.
2979: Use `PetscDSRestoreTabulation()` to restore the array
2981: Developer Note:
2982: The Fortran language syntax does not directly support arrays of pointers, the '%ptr' notation allows mimicking their use in Fortran.
2984: .seealso: `PetscDS`, `PetscTabulation`, `PetscDSCreate()`
2985: @*/
2986: PetscErrorCode PetscDSGetTabulation(PetscDS prob, PetscTabulation *T[]) PeNS
2987: {
2988: PetscFunctionBegin;
2990: PetscAssertPointer(T, 2);
2991: PetscCall(PetscDSSetUp(prob));
2992: *T = prob->T;
2993: PetscFunctionReturn(PETSC_SUCCESS);
2994: }
2996: /*@C
2997: PetscDSGetFaceTabulation - Return the basis tabulation at quadrature points on the faces
2999: Not Collective
3001: Input Parameter:
3002: . prob - The `PetscDS` object
3004: Output Parameter:
3005: . Tf - The basis function and derivative tabulation on each local face at quadrature points for each field
3007: Level: intermediate
3009: Note:
3010: The tabulation is only valid so long as the `PetscDS` has not be destroyed. There is no `PetscDSRestoreFaceTabulation()` in C.
3012: .seealso: `PetscTabulation`, `PetscDS`, `PetscDSGetTabulation()`, `PetscDSCreate()`
3013: @*/
3014: PetscErrorCode PetscDSGetFaceTabulation(PetscDS prob, PetscTabulation *Tf[])
3015: {
3016: PetscFunctionBegin;
3018: PetscAssertPointer(Tf, 2);
3019: PetscCall(PetscDSSetUp(prob));
3020: *Tf = prob->Tf;
3021: PetscFunctionReturn(PETSC_SUCCESS);
3022: }
3024: PetscErrorCode PetscDSGetEvaluationArrays(PetscDS prob, PetscScalar *u[], PetscScalar *u_t[], PetscScalar *u_x[])
3025: {
3026: PetscFunctionBegin;
3028: PetscCall(PetscDSSetUp(prob));
3029: if (u) {
3030: PetscAssertPointer(u, 2);
3031: *u = prob->u;
3032: }
3033: if (u_t) {
3034: PetscAssertPointer(u_t, 3);
3035: *u_t = prob->u_t;
3036: }
3037: if (u_x) {
3038: PetscAssertPointer(u_x, 4);
3039: *u_x = prob->u_x;
3040: }
3041: PetscFunctionReturn(PETSC_SUCCESS);
3042: }
3044: PetscErrorCode PetscDSGetWeakFormArrays(PetscDS prob, PetscScalar *f0[], PetscScalar *f1[], PetscScalar *g0[], PetscScalar *g1[], PetscScalar *g2[], PetscScalar *g3[])
3045: {
3046: PetscFunctionBegin;
3048: PetscCall(PetscDSSetUp(prob));
3049: if (f0) {
3050: PetscAssertPointer(f0, 2);
3051: *f0 = prob->f0;
3052: }
3053: if (f1) {
3054: PetscAssertPointer(f1, 3);
3055: *f1 = prob->f1;
3056: }
3057: if (g0) {
3058: PetscAssertPointer(g0, 4);
3059: *g0 = prob->g0;
3060: }
3061: if (g1) {
3062: PetscAssertPointer(g1, 5);
3063: *g1 = prob->g1;
3064: }
3065: if (g2) {
3066: PetscAssertPointer(g2, 6);
3067: *g2 = prob->g2;
3068: }
3069: if (g3) {
3070: PetscAssertPointer(g3, 7);
3071: *g3 = prob->g3;
3072: }
3073: PetscFunctionReturn(PETSC_SUCCESS);
3074: }
3076: PetscErrorCode PetscDSGetWorkspace(PetscDS prob, PetscReal **x, PetscScalar **basisReal, PetscScalar **basisDerReal, PetscScalar **testReal, PetscScalar **testDerReal)
3077: {
3078: PetscFunctionBegin;
3080: PetscCall(PetscDSSetUp(prob));
3081: if (x) {
3082: PetscAssertPointer(x, 2);
3083: *x = prob->x;
3084: }
3085: if (basisReal) {
3086: PetscAssertPointer(basisReal, 3);
3087: *basisReal = prob->basisReal;
3088: }
3089: if (basisDerReal) {
3090: PetscAssertPointer(basisDerReal, 4);
3091: *basisDerReal = prob->basisDerReal;
3092: }
3093: if (testReal) {
3094: PetscAssertPointer(testReal, 5);
3095: *testReal = prob->testReal;
3096: }
3097: if (testDerReal) {
3098: PetscAssertPointer(testDerReal, 6);
3099: *testDerReal = prob->testDerReal;
3100: }
3101: PetscFunctionReturn(PETSC_SUCCESS);
3102: }
3104: /*@C
3105: PetscDSAddBoundary - Add a boundary condition to the model.
3107: Collective
3109: Input Parameters:
3110: + ds - The `PetscDS` object
3111: . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
3112: . name - The name for the boundary condition
3113: . label - The label defining constrained points
3114: . Nv - The number of `DMLabel` values for constrained points
3115: . values - An array of label values for constrained points
3116: . field - The field to constrain
3117: . Nc - The number of constrained field components (0 will constrain all fields)
3118: . comps - An array of constrained component numbers
3119: . bcFunc - A pointwise function giving boundary values
3120: . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or `NULL`
3121: - ctx - An optional user context for `bcFunc`
3123: Output Parameter:
3124: . bd - The boundary number
3126: Options Database Keys:
3127: + -bc_NAME values - comma separated list of values for the boundary condition NAME
3128: - -bc_NAME_comp comps - comma separated list of components for the boundary condition NAME
3130: Level: developer
3132: Note:
3133: Both `bcFunc` and `bcFunc_t` will depend on the boundary condition type. If the type if `DM_BC_ESSENTIAL`, then the calling sequence is\:
3134: .vb
3135: void bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])
3136: .ve
3138: If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, then the calling sequence is\:
3139: .vb
3140: void bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
3141: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
3142: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
3143: PetscReal time, const PetscReal x[], PetscScalar bcval[])
3144: .ve
3145: + dim - the coordinate dimension
3146: . Nf - the number of fields
3147: . uOff - the offset into u[] and u_t[] for each field
3148: . uOff_x - the offset into u_x[] for each field
3149: . u - each field evaluated at the current point
3150: . u_t - the time derivative of each field evaluated at the current point
3151: . u_x - the gradient of each field evaluated at the current point
3152: . aOff - the offset into a[] and a_t[] for each auxiliary field
3153: . aOff_x - the offset into a_x[] for each auxiliary field
3154: . a - each auxiliary field evaluated at the current point
3155: . a_t - the time derivative of each auxiliary field evaluated at the current point
3156: . a_x - the gradient of auxiliary each field evaluated at the current point
3157: . t - current time
3158: . x - coordinates of the current point
3159: . numConstants - number of constant parameters
3160: . constants - constant parameters
3161: - bcval - output values at the current point
3163: Notes:
3164: The pointwise functions are used to provide boundary values for essential boundary
3165: conditions. In FEM, they are acting upon by dual basis functionals to generate FEM
3166: coefficients which are fixed. Natural boundary conditions signal to PETSc that boundary
3167: integrals should be performed, using the kernels from `PetscDSSetBdResidual()`.
3169: .seealso: `PetscDS`, `PetscWeakForm`, `DMLabel`, `DMBoundaryConditionType`, `PetscDSAddBoundaryByName()`, `PetscDSGetBoundary()`, `PetscDSSetResidual()`, `PetscDSSetBdResidual()`
3170: @*/
3171: PetscErrorCode PetscDSAddBoundary(PetscDS ds, DMBoundaryConditionType type, const char name[], DMLabel label, PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], PetscVoidFn *bcFunc, PetscVoidFn *bcFunc_t, PetscCtx ctx, PetscInt *bd)
3172: {
3173: DSBoundary head = ds->boundary, b;
3174: PetscInt n = 0;
3175: const char *lname;
3177: PetscFunctionBegin;
3180: PetscAssertPointer(name, 3);
3185: 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);
3186: if (Nc > 0) {
3187: PetscInt *fcomps;
3188: PetscInt c;
3190: PetscCall(PetscDSGetComponents(ds, &fcomps));
3191: 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);
3192: for (c = 0; c < Nc; ++c) {
3193: 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);
3194: }
3195: }
3196: PetscCall(PetscNew(&b));
3197: PetscCall(PetscStrallocpy(name, (char **)&b->name));
3198: PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf));
3199: PetscCall(PetscWeakFormSetNumFields(b->wf, ds->Nf));
3200: PetscCall(PetscMalloc1(Nv, &b->values));
3201: if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv));
3202: PetscCall(PetscMalloc1(Nc, &b->comps));
3203: if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc));
3204: PetscCall(PetscObjectGetName((PetscObject)label, &lname));
3205: PetscCall(PetscStrallocpy(lname, (char **)&b->lname));
3206: b->type = type;
3207: b->label = label;
3208: b->Nv = Nv;
3209: b->field = field;
3210: b->Nc = Nc;
3211: b->func = bcFunc;
3212: b->func_t = bcFunc_t;
3213: b->ctx = ctx;
3214: b->next = NULL;
3215: /* Append to linked list so that we can preserve the order */
3216: if (!head) ds->boundary = b;
3217: while (head) {
3218: if (!head->next) {
3219: head->next = b;
3220: head = b;
3221: }
3222: head = head->next;
3223: ++n;
3224: }
3225: if (bd) {
3226: PetscAssertPointer(bd, 13);
3227: *bd = n;
3228: }
3229: PetscFunctionReturn(PETSC_SUCCESS);
3230: }
3232: // PetscClangLinter pragma ignore: -fdoc-section-header-unknown
3233: /*@C
3234: PetscDSAddBoundaryByName - Add a boundary condition to the model.
3236: Collective
3238: Input Parameters:
3239: + ds - The `PetscDS` object
3240: . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
3241: . name - The boundary condition name
3242: . lname - The name of the label defining constrained points
3243: . Nv - The number of `DMLabel` values for constrained points
3244: . values - An array of label values for constrained points
3245: . field - The field to constrain
3246: . Nc - The number of constrained field components (0 will constrain all fields)
3247: . comps - An array of constrained component numbers
3248: . bcFunc - A pointwise function giving boundary values
3249: . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or `NULL`
3250: - ctx - An optional user context for `bcFunc`
3252: Output Parameter:
3253: . bd - The boundary number
3255: Options Database Keys:
3256: + -bc_NAME values - comma separated list of values for the boundary condition NAME
3257: - -bc_NAME_comp comps - comma separated list of components for the boundary condition NAME
3259: Calling Sequence of `bcFunc` and `bcFunc_t`:
3260: If the type is `DM_BC_ESSENTIAL`
3261: .vb
3262: void bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[])
3263: .ve
3264: If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value,
3265: .vb
3266: void bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux,
3267: const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
3268: const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
3269: PetscReal time, const PetscReal x[], PetscScalar bcval[])
3270: .ve
3271: + dim - the coordinate dimension
3272: . Nf - the number of fields
3273: . uOff - the offset into `u`[] and `u_t`[] for each field
3274: . uOff_x - the offset into `u_x`[] for each field
3275: . u - each field evaluated at the current point
3276: . u_t - the time derivative of each field evaluated at the current point
3277: . u_x - the gradient of each field evaluated at the current point
3278: . aOff - the offset into `a`[] and `a_t`[] for each auxiliary field
3279: . aOff_x - the offset into `a_x`[] for each auxiliary field
3280: . a - each auxiliary field evaluated at the current point
3281: . a_t - the time derivative of each auxiliary field evaluated at the current point
3282: . a_x - the gradient of auxiliary each field evaluated at the current point
3283: . t - current time
3284: . x - coordinates of the current point
3285: . numConstants - number of constant parameters
3286: . constants - constant parameters
3287: - bcval - output values at the current point
3289: Level: developer
3291: Notes:
3292: The pointwise functions are used to provide boundary values for essential boundary
3293: conditions. In FEM, they are acting upon by dual basis functionals to generate FEM
3294: coefficients which are fixed. Natural boundary conditions signal to PETSc that boundary
3295: integrals should be performed, using the kernels from `PetscDSSetBdResidual()`.
3297: This function should only be used with `DMFOREST` currently, since labels cannot be defined before the underlying `DMPLEX` is built.
3299: .seealso: `PetscDS`, `PetscWeakForm`, `DMLabel`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSSetResidual()`, `PetscDSSetBdResidual()`
3300: @*/
3301: PetscErrorCode PetscDSAddBoundaryByName(PetscDS ds, DMBoundaryConditionType type, const char name[], const char lname[], PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], PetscVoidFn *bcFunc, PetscVoidFn *bcFunc_t, PetscCtx ctx, PetscInt *bd)
3302: {
3303: DSBoundary head = ds->boundary, b;
3304: PetscInt n = 0;
3306: PetscFunctionBegin;
3309: PetscAssertPointer(name, 3);
3310: PetscAssertPointer(lname, 4);
3314: PetscCall(PetscNew(&b));
3315: PetscCall(PetscStrallocpy(name, (char **)&b->name));
3316: PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf));
3317: PetscCall(PetscWeakFormSetNumFields(b->wf, ds->Nf));
3318: PetscCall(PetscMalloc1(Nv, &b->values));
3319: if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv));
3320: PetscCall(PetscMalloc1(Nc, &b->comps));
3321: if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc));
3322: PetscCall(PetscStrallocpy(lname, (char **)&b->lname));
3323: b->type = type;
3324: b->label = NULL;
3325: b->Nv = Nv;
3326: b->field = field;
3327: b->Nc = Nc;
3328: b->func = bcFunc;
3329: b->func_t = bcFunc_t;
3330: b->ctx = ctx;
3331: b->next = NULL;
3332: /* Append to linked list so that we can preserve the order */
3333: if (!head) ds->boundary = b;
3334: while (head) {
3335: if (!head->next) {
3336: head->next = b;
3337: head = b;
3338: }
3339: head = head->next;
3340: ++n;
3341: }
3342: if (bd) {
3343: PetscAssertPointer(bd, 13);
3344: *bd = n;
3345: }
3346: PetscFunctionReturn(PETSC_SUCCESS);
3347: }
3349: /*@C
3350: PetscDSUpdateBoundary - Change a boundary condition for the model.
3352: Input Parameters:
3353: + ds - The `PetscDS` object
3354: . bd - The boundary condition number
3355: . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
3356: . name - The boundary condition name
3357: . label - The label defining constrained points
3358: . Nv - The number of `DMLabel` ids for constrained points
3359: . values - An array of ids for constrained points
3360: . field - The field to constrain
3361: . Nc - The number of constrained field components
3362: . comps - An array of constrained component numbers
3363: . bcFunc - A pointwise function giving boundary values
3364: . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or `NULL`
3365: - ctx - An optional user context for `bcFunc`
3367: Level: developer
3369: Notes:
3370: The pointwise functions are used to provide boundary values for essential boundary
3371: conditions. In FEM, they are acting upon by dual basis functionals to generate FEM
3372: coefficients which are fixed. Natural boundary conditions signal to PETSc that boundary
3373: integrals should be performed, using the kernels from `PetscDSSetBdResidual()`.
3375: The boundary condition number is the order in which it was registered. The user can get the number of boundary conditions from `PetscDSGetNumBoundary()`.
3376: See `PetscDSAddBoundary()` for a description of the calling sequences for the callbacks.
3378: .seealso: `PetscDS`, `PetscWeakForm`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSGetNumBoundary()`, `DMLabel`
3379: @*/
3380: 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[], PetscVoidFn *bcFunc, PetscVoidFn *bcFunc_t, PetscCtx ctx)
3381: {
3382: DSBoundary b = ds->boundary;
3383: PetscInt n = 0;
3385: PetscFunctionBegin;
3387: while (b) {
3388: if (n == bd) break;
3389: b = b->next;
3390: ++n;
3391: }
3392: PetscCheck(b, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bd, n);
3393: if (name) {
3394: PetscCall(PetscFree(b->name));
3395: PetscCall(PetscStrallocpy(name, (char **)&b->name));
3396: }
3397: b->type = type;
3398: if (label) {
3399: const char *name;
3401: b->label = label;
3402: PetscCall(PetscFree(b->lname));
3403: PetscCall(PetscObjectGetName((PetscObject)label, &name));
3404: PetscCall(PetscStrallocpy(name, (char **)&b->lname));
3405: }
3406: if (Nv >= 0) {
3407: b->Nv = Nv;
3408: PetscCall(PetscFree(b->values));
3409: PetscCall(PetscMalloc1(Nv, &b->values));
3410: if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv));
3411: }
3412: if (field >= 0) b->field = field;
3413: if (Nc >= 0) {
3414: b->Nc = Nc;
3415: PetscCall(PetscFree(b->comps));
3416: PetscCall(PetscMalloc1(Nc, &b->comps));
3417: if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc));
3418: }
3419: if (bcFunc) b->func = bcFunc;
3420: if (bcFunc_t) b->func_t = bcFunc_t;
3421: if (ctx) b->ctx = ctx;
3422: PetscFunctionReturn(PETSC_SUCCESS);
3423: }
3425: /*@
3426: PetscDSGetNumBoundary - Get the number of registered boundary conditions
3428: Input Parameter:
3429: . ds - The `PetscDS` object
3431: Output Parameter:
3432: . numBd - The number of boundary conditions
3434: Level: intermediate
3436: .seealso: `PetscDS`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`
3437: @*/
3438: PetscErrorCode PetscDSGetNumBoundary(PetscDS ds, PetscInt *numBd)
3439: {
3440: DSBoundary b = ds->boundary;
3442: PetscFunctionBegin;
3444: PetscAssertPointer(numBd, 2);
3445: *numBd = 0;
3446: while (b) {
3447: ++(*numBd);
3448: b = b->next;
3449: }
3450: PetscFunctionReturn(PETSC_SUCCESS);
3451: }
3453: /*@C
3454: PetscDSGetBoundary - Gets a boundary condition from the model
3456: Input Parameters:
3457: + ds - The `PetscDS` object
3458: - bd - The boundary condition number
3460: Output Parameters:
3461: + wf - The `PetscWeakForm` holding the pointwise functions
3462: . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann)
3463: . name - The boundary condition name
3464: . label - The label defining constrained points
3465: . Nv - The number of `DMLabel` ids for constrained points
3466: . values - An array of ids for constrained points
3467: . field - The field to constrain
3468: . Nc - The number of constrained field components
3469: . comps - An array of constrained component numbers
3470: . func - A pointwise function giving boundary values
3471: . func_t - A pointwise function giving the time derivative of the boundary values
3472: - ctx - An optional user context for `bcFunc`
3474: Level: developer
3476: .seealso: `PetscDS`, `PetscWeakForm`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `DMLabel`
3477: @*/
3478: 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[], PetscVoidFn **func, PetscVoidFn **func_t, void **ctx)
3479: {
3480: DSBoundary b = ds->boundary;
3481: PetscInt n = 0;
3483: PetscFunctionBegin;
3485: while (b) {
3486: if (n == bd) break;
3487: b = b->next;
3488: ++n;
3489: }
3490: PetscCheck(b, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bd, n);
3491: if (wf) {
3492: PetscAssertPointer(wf, 3);
3493: *wf = b->wf;
3494: }
3495: if (type) {
3496: PetscAssertPointer(type, 4);
3497: *type = b->type;
3498: }
3499: if (name) {
3500: PetscAssertPointer(name, 5);
3501: *name = b->name;
3502: }
3503: if (label) {
3504: PetscAssertPointer(label, 6);
3505: *label = b->label;
3506: }
3507: if (Nv) {
3508: PetscAssertPointer(Nv, 7);
3509: *Nv = b->Nv;
3510: }
3511: if (values) {
3512: PetscAssertPointer(values, 8);
3513: *values = b->values;
3514: }
3515: if (field) {
3516: PetscAssertPointer(field, 9);
3517: *field = b->field;
3518: }
3519: if (Nc) {
3520: PetscAssertPointer(Nc, 10);
3521: *Nc = b->Nc;
3522: }
3523: if (comps) {
3524: PetscAssertPointer(comps, 11);
3525: *comps = b->comps;
3526: }
3527: if (func) {
3528: PetscAssertPointer(func, 12);
3529: *func = b->func;
3530: }
3531: if (func_t) {
3532: PetscAssertPointer(func_t, 13);
3533: *func_t = b->func_t;
3534: }
3535: if (ctx) {
3536: PetscAssertPointer(ctx, 14);
3537: *ctx = b->ctx;
3538: }
3539: PetscFunctionReturn(PETSC_SUCCESS);
3540: }
3542: /*@
3543: PetscDSUpdateBoundaryLabels - Update `DMLabel` in each boundary condition using the label name and the input `DM`
3545: Not Collective
3547: Input Parameters:
3548: + ds - The source `PetscDS` object
3549: - dm - The `DM` holding labels
3551: Level: intermediate
3553: .seealso: `PetscDS`, `DMBoundary`, `DM`, `PetscDSCopyBoundary()`, `PetscDSCreate()`, `DMGetLabel()`
3554: @*/
3555: PetscErrorCode PetscDSUpdateBoundaryLabels(PetscDS ds, DM dm)
3556: {
3557: DSBoundary b;
3559: PetscFunctionBegin;
3562: for (b = ds->boundary; b; b = b->next) {
3563: if (b->lname) PetscCall(DMGetLabel(dm, b->lname, &b->label));
3564: }
3565: PetscFunctionReturn(PETSC_SUCCESS);
3566: }
3568: static PetscErrorCode DSBoundaryDuplicate_Internal(DSBoundary b, DSBoundary *bNew)
3569: {
3570: PetscFunctionBegin;
3571: PetscCall(PetscNew(bNew));
3572: PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &(*bNew)->wf));
3573: PetscCall(PetscWeakFormCopy(b->wf, (*bNew)->wf));
3574: PetscCall(PetscStrallocpy(b->name, (char **)&((*bNew)->name)));
3575: PetscCall(PetscStrallocpy(b->lname, (char **)&((*bNew)->lname)));
3576: (*bNew)->type = b->type;
3577: (*bNew)->label = b->label;
3578: (*bNew)->Nv = b->Nv;
3579: PetscCall(PetscMalloc1(b->Nv, &(*bNew)->values));
3580: PetscCall(PetscArraycpy((*bNew)->values, b->values, b->Nv));
3581: (*bNew)->field = b->field;
3582: (*bNew)->Nc = b->Nc;
3583: PetscCall(PetscMalloc1(b->Nc, &(*bNew)->comps));
3584: PetscCall(PetscArraycpy((*bNew)->comps, b->comps, b->Nc));
3585: (*bNew)->func = b->func;
3586: (*bNew)->func_t = b->func_t;
3587: (*bNew)->ctx = b->ctx;
3588: PetscFunctionReturn(PETSC_SUCCESS);
3589: }
3591: /*@
3592: PetscDSCopyBoundary - Copy all boundary condition objects to the new `PetscDS`
3594: Not Collective
3596: Input Parameters:
3597: + ds - The source `PetscDS` object
3598: . numFields - The number of selected fields, or `PETSC_DEFAULT` for all fields
3599: - fields - The selected fields, or `NULL` for all fields
3601: Output Parameter:
3602: . newds - The target `PetscDS`, now with a copy of the boundary conditions
3604: Level: intermediate
3606: .seealso: `PetscDS`, `DMBoundary`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3607: @*/
3608: PetscErrorCode PetscDSCopyBoundary(PetscDS ds, PetscInt numFields, const PetscInt fields[], PetscDS newds)
3609: {
3610: DSBoundary b, *lastnext;
3612: PetscFunctionBegin;
3615: if (ds == newds) PetscFunctionReturn(PETSC_SUCCESS);
3616: PetscCall(PetscDSDestroyBoundary(newds));
3617: lastnext = &newds->boundary;
3618: for (b = ds->boundary; b; b = b->next) {
3619: DSBoundary bNew;
3620: PetscInt fieldNew = -1;
3622: if (numFields > 0 && fields) {
3623: PetscInt f;
3625: for (f = 0; f < numFields; ++f)
3626: if (b->field == fields[f]) break;
3627: if (f == numFields) continue;
3628: fieldNew = f;
3629: }
3630: PetscCall(DSBoundaryDuplicate_Internal(b, &bNew));
3631: bNew->field = fieldNew < 0 ? b->field : fieldNew;
3632: *lastnext = bNew;
3633: lastnext = &bNew->next;
3634: }
3635: PetscFunctionReturn(PETSC_SUCCESS);
3636: }
3638: /*@
3639: PetscDSDestroyBoundary - Remove all `DMBoundary` objects from the `PetscDS`
3641: Not Collective
3643: Input Parameter:
3644: . ds - The `PetscDS` object
3646: Level: intermediate
3648: .seealso: `PetscDS`, `DMBoundary`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`
3649: @*/
3650: PetscErrorCode PetscDSDestroyBoundary(PetscDS ds)
3651: {
3652: DSBoundary next = ds->boundary;
3654: PetscFunctionBegin;
3655: while (next) {
3656: DSBoundary b = next;
3658: next = b->next;
3659: PetscCall(PetscWeakFormDestroy(&b->wf));
3660: PetscCall(PetscFree(b->name));
3661: PetscCall(PetscFree(b->lname));
3662: PetscCall(PetscFree(b->values));
3663: PetscCall(PetscFree(b->comps));
3664: PetscCall(PetscFree(b));
3665: }
3666: PetscFunctionReturn(PETSC_SUCCESS);
3667: }
3669: /*@
3670: PetscDSSelectDiscretizations - Copy discretizations to the new `PetscDS` with different field layout
3672: Not Collective
3674: Input Parameters:
3675: + prob - The `PetscDS` object
3676: . numFields - Number of new fields
3677: . fields - Old field number for each new field
3678: . minDegree - Minimum degree for a discretization, or `PETSC_DETERMINE` for no limit
3679: - maxDegree - Maximum degree for a discretization, or `PETSC_DETERMINE` for no limit
3681: Output Parameter:
3682: . newprob - The `PetscDS` copy
3684: Level: intermediate
3686: .seealso: `PetscDS`, `PetscDSSelectEquations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3687: @*/
3688: PetscErrorCode PetscDSSelectDiscretizations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscInt minDegree, PetscInt maxDegree, PetscDS newprob)
3689: {
3690: PetscInt Nf, Nfn, fn;
3692: PetscFunctionBegin;
3694: if (fields) PetscAssertPointer(fields, 3);
3696: PetscCall(PetscDSGetNumFields(prob, &Nf));
3697: PetscCall(PetscDSGetNumFields(newprob, &Nfn));
3698: numFields = numFields < 0 ? Nf : numFields;
3699: for (fn = 0; fn < numFields; ++fn) {
3700: const PetscInt f = fields ? fields[fn] : fn;
3701: PetscObject disc;
3702: PetscClassId id;
3704: if (f >= Nf) continue;
3705: PetscCall(PetscDSGetDiscretization(prob, f, &disc));
3706: PetscCallContinue(PetscObjectGetClassId(disc, &id));
3707: if (id == PETSCFE_CLASSID) {
3708: PetscFE fe;
3710: PetscCall(PetscFELimitDegree((PetscFE)disc, minDegree, maxDegree, &fe));
3711: PetscCall(PetscDSSetDiscretization(newprob, fn, (PetscObject)fe));
3712: PetscCall(PetscFEDestroy(&fe));
3713: } else {
3714: PetscCall(PetscDSSetDiscretization(newprob, fn, disc));
3715: }
3716: }
3717: PetscFunctionReturn(PETSC_SUCCESS);
3718: }
3720: /*@
3721: PetscDSSelectEquations - Copy pointwise function pointers to the new `PetscDS` with different field layout
3723: Not Collective
3725: Input Parameters:
3726: + prob - The `PetscDS` object
3727: . numFields - Number of new fields
3728: - fields - Old field number for each new field
3730: Output Parameter:
3731: . newprob - The `PetscDS` copy
3733: Level: intermediate
3735: .seealso: `PetscDS`, `PetscDSSelectDiscretizations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3736: @*/
3737: PetscErrorCode PetscDSSelectEquations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob)
3738: {
3739: PetscInt Nf, Nfn, fn, gn;
3741: PetscFunctionBegin;
3743: if (fields) PetscAssertPointer(fields, 3);
3745: PetscCall(PetscDSGetNumFields(prob, &Nf));
3746: PetscCall(PetscDSGetNumFields(newprob, &Nfn));
3747: PetscCheck(numFields <= Nfn, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_SIZ, "Number of fields %" PetscInt_FMT " to transfer must not be greater than the total number of fields %" PetscInt_FMT, numFields, Nfn);
3748: for (fn = 0; fn < numFields; ++fn) {
3749: const PetscInt f = fields ? fields[fn] : fn;
3750: PetscPointFn *obj;
3751: PetscPointFn *f0, *f1;
3752: PetscBdPointFn *f0Bd, *f1Bd;
3753: PetscRiemannFn *r;
3755: if (f >= Nf) continue;
3756: PetscCall(PetscDSGetObjective(prob, f, &obj));
3757: PetscCall(PetscDSGetResidual(prob, f, &f0, &f1));
3758: PetscCall(PetscDSGetBdResidual(prob, f, &f0Bd, &f1Bd));
3759: PetscCall(PetscDSGetRiemannSolver(prob, f, &r));
3760: PetscCall(PetscDSSetObjective(newprob, fn, obj));
3761: PetscCall(PetscDSSetResidual(newprob, fn, f0, f1));
3762: PetscCall(PetscDSSetBdResidual(newprob, fn, f0Bd, f1Bd));
3763: PetscCall(PetscDSSetRiemannSolver(newprob, fn, r));
3764: for (gn = 0; gn < numFields; ++gn) {
3765: const PetscInt g = fields ? fields[gn] : gn;
3766: PetscPointJacFn *g0, *g1, *g2, *g3;
3767: PetscPointJacFn *g0p, *g1p, *g2p, *g3p;
3768: PetscBdPointJacFn *g0Bd, *g1Bd, *g2Bd, *g3Bd;
3770: if (g >= Nf) continue;
3771: PetscCall(PetscDSGetJacobian(prob, f, g, &g0, &g1, &g2, &g3));
3772: PetscCall(PetscDSGetJacobianPreconditioner(prob, f, g, &g0p, &g1p, &g2p, &g3p));
3773: PetscCall(PetscDSGetBdJacobian(prob, f, g, &g0Bd, &g1Bd, &g2Bd, &g3Bd));
3774: PetscCall(PetscDSSetJacobian(newprob, fn, gn, g0, g1, g2, g3));
3775: PetscCall(PetscDSSetJacobianPreconditioner(newprob, fn, gn, g0p, g1p, g2p, g3p));
3776: PetscCall(PetscDSSetBdJacobian(newprob, fn, gn, g0Bd, g1Bd, g2Bd, g3Bd));
3777: }
3778: }
3779: PetscFunctionReturn(PETSC_SUCCESS);
3780: }
3782: /*@
3783: PetscDSCopyEquations - Copy all pointwise function pointers to another `PetscDS`
3785: Not Collective
3787: Input Parameter:
3788: . prob - The `PetscDS` object
3790: Output Parameter:
3791: . newprob - The `PetscDS` copy
3793: Level: intermediate
3795: .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3796: @*/
3797: PetscErrorCode PetscDSCopyEquations(PetscDS prob, PetscDS newprob)
3798: {
3799: PetscWeakForm wf, newwf;
3800: PetscInt Nf, Ng;
3802: PetscFunctionBegin;
3805: PetscCall(PetscDSGetNumFields(prob, &Nf));
3806: PetscCall(PetscDSGetNumFields(newprob, &Ng));
3807: PetscCheck(Nf == Ng, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_SIZ, "Number of fields must match %" PetscInt_FMT " != %" PetscInt_FMT, Nf, Ng);
3808: PetscCall(PetscDSGetWeakForm(prob, &wf));
3809: PetscCall(PetscDSGetWeakForm(newprob, &newwf));
3810: PetscCall(PetscWeakFormCopy(wf, newwf));
3811: PetscFunctionReturn(PETSC_SUCCESS);
3812: }
3814: /*@
3815: PetscDSCopyConstants - Copy all constants set with `PetscDSSetConstants()` to another `PetscDS`
3817: Not Collective
3819: Input Parameter:
3820: . prob - The `PetscDS` object
3822: Output Parameter:
3823: . newprob - The `PetscDS` copy
3825: Level: intermediate
3827: .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3828: @*/
3829: PetscErrorCode PetscDSCopyConstants(PetscDS prob, PetscDS newprob)
3830: {
3831: PetscInt Nc;
3832: const PetscScalar *constants;
3834: PetscFunctionBegin;
3837: PetscCall(PetscDSGetConstants(prob, &Nc, &constants));
3838: PetscCall(PetscDSSetConstants(newprob, Nc, (PetscScalar *)constants));
3839: PetscFunctionReturn(PETSC_SUCCESS);
3840: }
3842: /*@
3843: PetscDSCopyExactSolutions - Copy all exact solutions set with `PetscDSSetExactSolution()` and `PetscDSSetExactSolutionTimeDerivative()` to another `PetscDS`
3845: Not Collective
3847: Input Parameter:
3848: . ds - The `PetscDS` object
3850: Output Parameter:
3851: . newds - The `PetscDS` copy
3853: Level: intermediate
3855: .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSCopyBounds()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3856: @*/
3857: PetscErrorCode PetscDSCopyExactSolutions(PetscDS ds, PetscDS newds)
3858: {
3859: PetscSimplePointFn *sol;
3860: void *ctx;
3861: PetscInt Nf, f;
3863: PetscFunctionBegin;
3866: PetscCall(PetscDSGetNumFields(ds, &Nf));
3867: for (f = 0; f < Nf; ++f) {
3868: PetscCall(PetscDSGetExactSolution(ds, f, &sol, &ctx));
3869: PetscCall(PetscDSSetExactSolution(newds, f, sol, ctx));
3870: PetscCall(PetscDSGetExactSolutionTimeDerivative(ds, f, &sol, &ctx));
3871: PetscCall(PetscDSSetExactSolutionTimeDerivative(newds, f, sol, ctx));
3872: }
3873: PetscFunctionReturn(PETSC_SUCCESS);
3874: }
3876: /*@
3877: PetscDSCopyBounds - Copy lower and upper solution bounds set with `PetscDSSetLowerBound()` and `PetscDSSetLowerBound()` to another `PetscDS`
3879: Not Collective
3881: Input Parameter:
3882: . ds - The `PetscDS` object
3884: Output Parameter:
3885: . newds - The `PetscDS` copy
3887: Level: intermediate
3889: .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSCopyExactSolutions()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()`
3890: @*/
3891: PetscErrorCode PetscDSCopyBounds(PetscDS ds, PetscDS newds)
3892: {
3893: PetscSimplePointFn *bound;
3894: void *ctx;
3895: PetscInt Nf, f;
3897: PetscFunctionBegin;
3900: PetscCall(PetscDSGetNumFields(ds, &Nf));
3901: for (f = 0; f < Nf; ++f) {
3902: PetscCall(PetscDSGetLowerBound(ds, f, &bound, &ctx));
3903: PetscCall(PetscDSSetLowerBound(newds, f, bound, ctx));
3904: PetscCall(PetscDSGetUpperBound(ds, f, &bound, &ctx));
3905: PetscCall(PetscDSSetUpperBound(newds, f, bound, ctx));
3906: }
3907: PetscFunctionReturn(PETSC_SUCCESS);
3908: }
3910: PetscErrorCode PetscDSCopy(PetscDS ds, PetscInt minDegree, PetscInt maxDegree, DM dmNew, PetscDS dsNew)
3911: {
3912: DSBoundary b;
3913: PetscInt cdim, Nf, f, d;
3914: PetscBool isCohesive;
3915: void *ctx;
3917: PetscFunctionBegin;
3918: PetscCall(PetscDSCopyConstants(ds, dsNew));
3919: PetscCall(PetscDSCopyExactSolutions(ds, dsNew));
3920: PetscCall(PetscDSCopyBounds(ds, dsNew));
3921: PetscCall(PetscDSSelectDiscretizations(ds, PETSC_DETERMINE, NULL, minDegree, maxDegree, dsNew));
3922: PetscCall(PetscDSCopyEquations(ds, dsNew));
3923: PetscCall(PetscDSGetNumFields(ds, &Nf));
3924: for (f = 0; f < Nf; ++f) {
3925: PetscCall(PetscDSGetContext(ds, f, &ctx));
3926: PetscCall(PetscDSSetContext(dsNew, f, ctx));
3927: PetscCall(PetscDSGetCohesive(ds, f, &isCohesive));
3928: PetscCall(PetscDSSetCohesive(dsNew, f, isCohesive));
3929: PetscCall(PetscDSGetJetDegree(ds, f, &d));
3930: PetscCall(PetscDSSetJetDegree(dsNew, f, d));
3931: }
3932: if (Nf) {
3933: PetscCall(PetscDSGetCoordinateDimension(ds, &cdim));
3934: PetscCall(PetscDSSetCoordinateDimension(dsNew, cdim));
3935: }
3936: PetscCall(PetscDSCopyBoundary(ds, PETSC_DETERMINE, NULL, dsNew));
3937: for (b = dsNew->boundary; b; b = b->next) {
3938: PetscCall(DMGetLabel(dmNew, b->lname, &b->label));
3939: /* Do not check if label exists here, since p4est calls this for the reference tree which does not have the labels */
3940: //PetscCheck(b->label,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s missing in new DM", name);
3941: }
3942: PetscFunctionReturn(PETSC_SUCCESS);
3943: }
3945: PetscErrorCode PetscDSGetHeightSubspace(PetscDS prob, PetscInt height, PetscDS *subprob)
3946: {
3947: PetscInt dim, Nf, f;
3949: PetscFunctionBegin;
3951: PetscAssertPointer(subprob, 3);
3952: if (height == 0) {
3953: *subprob = prob;
3954: PetscFunctionReturn(PETSC_SUCCESS);
3955: }
3956: PetscCall(PetscDSGetNumFields(prob, &Nf));
3957: PetscCall(PetscDSGetSpatialDimension(prob, &dim));
3958: PetscCheck(height <= dim, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_OUTOFRANGE, "DS can only handle height in [0, %" PetscInt_FMT "], not %" PetscInt_FMT, dim, height);
3959: if (!prob->subprobs) PetscCall(PetscCalloc1(dim, &prob->subprobs));
3960: if (!prob->subprobs[height - 1]) {
3961: PetscInt cdim;
3963: PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)prob), &prob->subprobs[height - 1]));
3964: PetscCall(PetscDSGetCoordinateDimension(prob, &cdim));
3965: PetscCall(PetscDSSetCoordinateDimension(prob->subprobs[height - 1], cdim));
3966: for (f = 0; f < Nf; ++f) {
3967: PetscFE subfe;
3968: PetscObject obj;
3969: PetscClassId id;
3971: PetscCall(PetscDSGetDiscretization(prob, f, &obj));
3972: PetscCall(PetscObjectGetClassId(obj, &id));
3973: PetscCheck(id == PETSCFE_CLASSID, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unsupported discretization type for field %" PetscInt_FMT, f);
3974: PetscCall(PetscFEGetHeightSubspace((PetscFE)obj, height, &subfe));
3975: PetscCall(PetscDSSetDiscretization(prob->subprobs[height - 1], f, (PetscObject)subfe));
3976: }
3977: }
3978: *subprob = prob->subprobs[height - 1];
3979: PetscFunctionReturn(PETSC_SUCCESS);
3980: }
3982: PetscErrorCode PetscDSPermuteQuadPoint(PetscDS ds, PetscInt ornt, PetscInt field, PetscInt q, PetscInt *qperm)
3983: {
3984: IS permIS;
3985: PetscQuadrature quad;
3986: DMPolytopeType ct;
3987: const PetscInt *perm;
3988: PetscInt Na, Nq;
3990: PetscFunctionBeginHot;
3991: PetscCall(PetscFEGetQuadrature((PetscFE)ds->disc[field], &quad));
3992: PetscCall(PetscQuadratureGetData(quad, NULL, NULL, &Nq, NULL, NULL));
3993: PetscCall(PetscQuadratureGetCellType(quad, &ct));
3994: PetscCheck(q >= 0 && q < Nq, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Quadrature point %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", q, Nq);
3995: Na = DMPolytopeTypeGetNumArrangements(ct) / 2;
3996: 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);
3997: if (!ds->quadPerm[(PetscInt)ct]) PetscCall(PetscQuadratureComputePermutations(quad, NULL, &ds->quadPerm[(PetscInt)ct]));
3998: permIS = ds->quadPerm[(PetscInt)ct][ornt + Na];
3999: PetscCall(ISGetIndices(permIS, &perm));
4000: *qperm = perm[q];
4001: PetscCall(ISRestoreIndices(permIS, &perm));
4002: PetscFunctionReturn(PETSC_SUCCESS);
4003: }
4005: PetscErrorCode PetscDSGetDiscType_Internal(PetscDS ds, PetscInt f, PetscDiscType *disctype)
4006: {
4007: PetscObject obj;
4008: PetscClassId id;
4009: PetscInt Nf;
4011: PetscFunctionBegin;
4013: PetscAssertPointer(disctype, 3);
4014: *disctype = PETSC_DISC_NONE;
4015: PetscCall(PetscDSGetNumFields(ds, &Nf));
4016: PetscCheck(f < Nf, PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_SIZ, "Field %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf);
4017: PetscCall(PetscDSGetDiscretization(ds, f, &obj));
4018: if (obj) {
4019: PetscCall(PetscObjectGetClassId(obj, &id));
4020: if (id == PETSCFE_CLASSID) *disctype = PETSC_DISC_FE;
4021: else *disctype = PETSC_DISC_FV;
4022: }
4023: PetscFunctionReturn(PETSC_SUCCESS);
4024: }
4026: static PetscErrorCode PetscDSDestroy_Basic(PetscDS ds)
4027: {
4028: PetscFunctionBegin;
4029: PetscCall(PetscFree(ds->data));
4030: PetscFunctionReturn(PETSC_SUCCESS);
4031: }
4033: static PetscErrorCode PetscDSInitialize_Basic(PetscDS ds)
4034: {
4035: PetscFunctionBegin;
4036: ds->ops->setfromoptions = NULL;
4037: ds->ops->setup = NULL;
4038: ds->ops->view = NULL;
4039: ds->ops->destroy = PetscDSDestroy_Basic;
4040: PetscFunctionReturn(PETSC_SUCCESS);
4041: }
4043: /*MC
4044: PETSCDSBASIC = "basic" - A discrete system with pointwise residual and boundary residual functions
4046: Level: intermediate
4048: .seealso: `PetscDSType`, `PetscDSCreate()`, `PetscDSSetType()`
4049: M*/
4051: PETSC_EXTERN PetscErrorCode PetscDSCreate_Basic(PetscDS ds)
4052: {
4053: PetscDS_Basic *b;
4055: PetscFunctionBegin;
4057: PetscCall(PetscNew(&b));
4058: ds->data = b;
4060: PetscCall(PetscDSInitialize_Basic(ds));
4061: PetscFunctionReturn(PETSC_SUCCESS);
4062: }