Actual source code: dmlocalts.c
petsc-3.8.4 2018-03-24
1: #include <petsc/private/dmimpl.h>
2: #include <petsc/private/tsimpl.h>
4: typedef struct {
5: PetscErrorCode (*boundarylocal)(DM,PetscReal,Vec,Vec,void*);
6: PetscErrorCode (*ifunctionlocal)(DM,PetscReal,Vec,Vec,Vec,void*);
7: PetscErrorCode (*ijacobianlocal)(DM,PetscReal,Vec,Vec,PetscReal,Mat,Mat,void*);
8: PetscErrorCode (*rhsfunctionlocal)(DM,PetscReal,Vec,Vec,void*);
9: void *boundarylocalctx;
10: void *ifunctionlocalctx;
11: void *ijacobianlocalctx;
12: void *rhsfunctionlocalctx;
13: } DMTS_Local;
15: static PetscErrorCode DMTSDestroy_DMLocal(DMTS tdm)
16: {
20: PetscFree(tdm->data);
21: return(0);
22: }
24: static PetscErrorCode DMTSDuplicate_DMLocal(DMTS oldtdm, DMTS tdm)
25: {
29: PetscNewLog(tdm, (DMTS_Local **) &tdm->data);
30: if (oldtdm->data) {PetscMemcpy(tdm->data, oldtdm->data, sizeof(DMTS_Local));}
31: return(0);
32: }
34: static PetscErrorCode DMLocalTSGetContext(DM dm, DMTS tdm, DMTS_Local **dmlocalts)
35: {
39: *dmlocalts = NULL;
40: if (!tdm->data) {
41: PetscNewLog(dm, (DMTS_Local **) &tdm->data);
43: tdm->ops->destroy = DMTSDestroy_DMLocal;
44: tdm->ops->duplicate = DMTSDuplicate_DMLocal;
45: }
46: *dmlocalts = (DMTS_Local *) tdm->data;
47: return(0);
48: }
50: static PetscErrorCode TSComputeIFunction_DMLocal(TS ts, PetscReal time, Vec X, Vec X_t, Vec F, void *ctx)
51: {
52: DM dm;
53: Vec locX, locX_t, locF;
54: DMTS_Local *dmlocalts = (DMTS_Local *) ctx;
62: TSGetDM(ts, &dm);
63: DMGetLocalVector(dm, &locX);
64: DMGetLocalVector(dm, &locX_t);
65: DMGetLocalVector(dm, &locF);
66: VecZeroEntries(locX);
67: VecZeroEntries(locX_t);
68: if (dmlocalts->boundarylocal) {(*dmlocalts->boundarylocal)(dm, time, locX, locX_t,dmlocalts->boundarylocalctx);}
69: DMGlobalToLocalBegin(dm, X, INSERT_VALUES, locX);
70: DMGlobalToLocalEnd(dm, X, INSERT_VALUES, locX);
71: DMGlobalToLocalBegin(dm, X_t, INSERT_VALUES, locX_t);
72: DMGlobalToLocalEnd(dm, X_t, INSERT_VALUES, locX_t);
73: VecZeroEntries(locF);
74: CHKMEMQ;
75: (*dmlocalts->ifunctionlocal)(dm, time, locX, locX_t, locF, dmlocalts->ifunctionlocalctx);
76: CHKMEMQ;
77: VecZeroEntries(F);
78: DMLocalToGlobalBegin(dm, locF, ADD_VALUES, F);
79: DMLocalToGlobalEnd(dm, locF, ADD_VALUES, F);
80: DMRestoreLocalVector(dm, &locX);
81: DMRestoreLocalVector(dm, &locX_t);
82: DMRestoreLocalVector(dm, &locF);
83: return(0);
84: }
86: static PetscErrorCode TSComputeRHSFunction_DMLocal(TS ts, PetscReal time, Vec X, Vec F, void *ctx)
87: {
88: DM dm;
89: Vec locX;
90: DMTS_Local *dmlocalts = (DMTS_Local *) ctx;
97: TSGetDM(ts, &dm);
98: DMGetLocalVector(dm, &locX);
99: VecZeroEntries(locX);
100: if (dmlocalts->boundarylocal) {(*dmlocalts->boundarylocal)(dm,time,locX,NULL,dmlocalts->boundarylocalctx);}
101: DMGlobalToLocalBegin(dm, X, INSERT_VALUES, locX);
102: DMGlobalToLocalEnd(dm, X, INSERT_VALUES, locX);
103: VecZeroEntries(F);
104: CHKMEMQ;
105: (*dmlocalts->rhsfunctionlocal)(dm, time, locX, F, dmlocalts->rhsfunctionlocalctx);
106: CHKMEMQ;
107: DMRestoreLocalVector(dm, &locX);
108: return(0);
109: }
111: static PetscErrorCode TSComputeIJacobian_DMLocal(TS ts, PetscReal time, Vec X, Vec X_t, PetscReal a, Mat A, Mat B, void *ctx)
112: {
113: DM dm;
114: Vec locX, locX_t;
115: DMTS_Local *dmlocalts = (DMTS_Local *) ctx;
119: TSGetDM(ts, &dm);
120: if (dmlocalts->ijacobianlocal) {
121: DMGetLocalVector(dm, &locX);
122: DMGetLocalVector(dm, &locX_t);
123: VecZeroEntries(locX);
124: if (dmlocalts->boundarylocal) {(*dmlocalts->boundarylocal)(dm,time,locX,locX_t,dmlocalts->boundarylocalctx);}
125: VecZeroEntries(locX_t);
126: DMGlobalToLocalBegin(dm, X, INSERT_VALUES, locX);
127: DMGlobalToLocalEnd(dm, X, INSERT_VALUES, locX);
128: DMGlobalToLocalBegin(dm, X_t, INSERT_VALUES, locX_t);
129: DMGlobalToLocalEnd(dm, X_t, INSERT_VALUES, locX_t);
130: CHKMEMQ;
131: (*dmlocalts->ijacobianlocal)(dm, time, locX, locX_t, a, A, B, dmlocalts->ijacobianlocalctx);
132: CHKMEMQ;
133: DMRestoreLocalVector(dm, &locX);
134: DMRestoreLocalVector(dm, &locX_t);
135: } else {
136: MatFDColoring fdcoloring;
137: PetscObjectQuery((PetscObject) dm, "DMDASNES_FDCOLORING", (PetscObject *) &fdcoloring);
138: if (!fdcoloring) {
139: ISColoring coloring;
141: DMCreateColoring(dm, dm->coloringtype, &coloring);
142: MatFDColoringCreate(B, coloring, &fdcoloring);
143: ISColoringDestroy(&coloring);
144: switch (dm->coloringtype) {
145: case IS_COLORING_GLOBAL:
146: MatFDColoringSetFunction(fdcoloring, (PetscErrorCode (*)(void)) TSComputeIFunction_DMLocal, dmlocalts);
147: break;
148: default: SETERRQ1(PetscObjectComm((PetscObject) ts), PETSC_ERR_SUP, "No support for coloring type '%s'", ISColoringTypes[dm->coloringtype]);
149: }
150: PetscObjectSetOptionsPrefix((PetscObject) fdcoloring, ((PetscObject) dm)->prefix);
151: MatFDColoringSetFromOptions(fdcoloring);
152: MatFDColoringSetUp(B, coloring, fdcoloring);
153: PetscObjectCompose((PetscObject) dm, "DMDASNES_FDCOLORING", (PetscObject) fdcoloring);
154: PetscObjectDereference((PetscObject) fdcoloring);
156: /* The following breaks an ugly reference counting loop that deserves a paragraph. MatFDColoringApply() will call
157: * VecDuplicate() with the state Vec and store inside the MatFDColoring. This Vec will duplicate the Vec, but the
158: * MatFDColoring is composed with the DM. We dereference the DM here so that the reference count will eventually
159: * drop to 0. Note the code in DMDestroy() that exits early for a negative reference count. That code path will be
160: * taken when the PetscObjectList for the Vec inside MatFDColoring is destroyed.
161: */
162: PetscObjectDereference((PetscObject) dm);
163: }
164: MatFDColoringApply(B, fdcoloring, X, ts);
165: }
166: /* This will be redundant if the user called both, but it's too common to forget. */
167: if (A != B) {
168: MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);
169: MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);
170: }
171: return(0);
172: }
174: /*@C
175: DMTSSetBoundaryLocal - set the function for essential boundary data for a local implicit function evaluation.
176: It should set the essential boundary data for the local portion of the solution X, as well its time derivative X_t (if it is not NULL).
177: Vectors are initialized to zero before this function, so it is only needed for non homogeneous data.
179: Note that this function is somewhat optional: boundary data could potentially be inserted by a function passed to
180: DMTSSetIFunctionLocal(). The use case for this function is for discretizations with constraints (see
181: DMGetDefaultConstraints()): this function inserts boundary values before constraint interpolation.
183: Logically Collective
185: Input Arguments:
186: + dm - DM to associate callback with
187: . func - local function evaluation
188: - ctx - context for function evaluation
190: Level: intermediate
192: .seealso: DMTSSetIFunction(), DMTSSetIJacobianLocal()
193: @*/
194: PetscErrorCode DMTSSetBoundaryLocal(DM dm, PetscErrorCode (*func)(DM, PetscReal, Vec, Vec, void *), void *ctx)
195: {
196: DMTS tdm;
197: DMTS_Local *dmlocalts;
202: DMGetDMTSWrite(dm, &tdm);
203: DMLocalTSGetContext(dm, tdm, &dmlocalts);
205: dmlocalts->boundarylocal = func;
206: dmlocalts->boundarylocalctx = ctx;
208: return(0);
209: }
211: /*@C
212: DMTSSetIFunctionLocal - set a local implicit function evaluation function. This function is called with local vector
213: containing the local vector information PLUS ghost point information. It should compute a result for all local
214: elements and DMTS will automatically accumulate the overlapping values.
216: Logically Collective
218: Input Arguments:
219: + dm - DM to associate callback with
220: . func - local function evaluation
221: - ctx - context for function evaluation
223: Level: beginner
225: .seealso: DMTSSetIFunction(), DMTSSetIJacobianLocal()
226: @*/
227: PetscErrorCode DMTSSetIFunctionLocal(DM dm, PetscErrorCode (*func)(DM, PetscReal, Vec, Vec, Vec, void *), void *ctx)
228: {
229: DMTS tdm;
230: DMTS_Local *dmlocalts;
235: DMGetDMTSWrite(dm, &tdm);
236: DMLocalTSGetContext(dm, tdm, &dmlocalts);
238: dmlocalts->ifunctionlocal = func;
239: dmlocalts->ifunctionlocalctx = ctx;
241: DMTSSetIFunction(dm, TSComputeIFunction_DMLocal, dmlocalts);
242: if (!tdm->ops->ijacobian) { /* Call us for the Jacobian too, can be overridden by the user. */
243: DMTSSetIJacobian(dm, TSComputeIJacobian_DMLocal, dmlocalts);
244: }
245: return(0);
246: }
248: /*@C
249: DMTSSetIJacobianLocal - set a local Jacobian evaluation function
251: Logically Collective
253: Input Arguments:
254: + dm - DM to associate callback with
255: . func - local Jacobian evaluation
256: - ctx - optional context for local Jacobian evaluation
258: Level: beginner
260: .seealso: DMTSSetIFunctionLocal(), DMTSSetIJacobian(), DMTSSetIFunction()
261: @*/
262: PetscErrorCode DMTSSetIJacobianLocal(DM dm, PetscErrorCode (*func)(DM, PetscReal, Vec, Vec, PetscReal, Mat, Mat, void *), void *ctx)
263: {
264: DMTS tdm;
265: DMTS_Local *dmlocalts;
270: DMGetDMTSWrite(dm, &tdm);
271: DMLocalTSGetContext(dm, tdm, &dmlocalts);
273: dmlocalts->ijacobianlocal = func;
274: dmlocalts->ijacobianlocalctx = ctx;
276: DMTSSetIJacobian(dm, TSComputeIJacobian_DMLocal, dmlocalts);
277: return(0);
278: }
280: /*@C
281: DMTSSetRHSFunctionLocal - set a local rhs function evaluation function. This function is called with local vector
282: containing the local vector information PLUS ghost point information. It should compute a result for all local
283: elements and DMTS will automatically accumulate the overlapping values.
285: Logically Collective
287: Input Arguments:
288: + dm - DM to associate callback with
289: . func - local function evaluation
290: - ctx - context for function evaluation
292: Level: beginner
294: .seealso: DMTSSetRHSFunction(), DMTSSetIFunction(), DMTSSetIJacobianLocal()
295: @*/
296: PetscErrorCode DMTSSetRHSFunctionLocal(DM dm, PetscErrorCode (*func)(DM, PetscReal, Vec, Vec, void *), void *ctx)
297: {
298: DMTS tdm;
299: DMTS_Local *dmlocalts;
304: DMGetDMTSWrite(dm, &tdm);
305: DMLocalTSGetContext(dm, tdm, &dmlocalts);
307: dmlocalts->rhsfunctionlocal = func;
308: dmlocalts->rhsfunctionlocalctx = ctx;
310: DMTSSetRHSFunction(dm, TSComputeRHSFunction_DMLocal, dmlocalts);
311: return(0);
312: }