xref: /petsc/src/ts/utils/dmdats.c (revision b00a91154f763f12aa55f3d53a3f2776f15f49e3)
1 #include <petscdmda.h>          /*I "petscdmda.h" I*/
2 #include <petsc-private/dmimpl.h>
3 #include <petsc-private/tsimpl.h>   /*I "petscts.h" I*/
4 #include <petscdraw.h>
5 
6 /* This structure holds the user-provided DMDA callbacks */
7 typedef struct {
8   PetscErrorCode (*ifunctionlocal)(DMDALocalInfo*,PetscReal,void*,void*,void*,void*);
9   PetscErrorCode (*rhsfunctionlocal)(DMDALocalInfo*,PetscReal,void*,void*,void*);
10   PetscErrorCode (*ijacobianlocal)(DMDALocalInfo*,PetscReal,void*,void*,PetscReal,Mat,Mat,MatStructure*,void*);
11   PetscErrorCode (*rhsjacobianlocal)(DMDALocalInfo*,PetscReal,void*,Mat,Mat,MatStructure*,void*);
12   void       *ifunctionlocalctx;
13   void       *ijacobianlocalctx;
14   void       *rhsfunctionlocalctx;
15   void       *rhsjacobianlocalctx;
16   InsertMode ifunctionlocalimode;
17   InsertMode rhsfunctionlocalimode;
18 } DMTS_DA;
19 
20 #undef __FUNCT__
21 #define __FUNCT__ "DMTSDestroy_DMDA"
22 static PetscErrorCode DMTSDestroy_DMDA(DMTS sdm)
23 {
24   PetscErrorCode ierr;
25 
26   PetscFunctionBegin;
27   ierr = PetscFree(sdm->data);CHKERRQ(ierr);
28   PetscFunctionReturn(0);
29 }
30 
31 #undef __FUNCT__
32 #define __FUNCT__ "DMTSDuplicate_DMDA"
33 static PetscErrorCode DMTSDuplicate_DMDA(DMTS oldsdm,DMTS sdm)
34 {
35   PetscErrorCode ierr;
36 
37   PetscFunctionBegin;
38   ierr = PetscNewLog(sdm,(DMTS_DA**)&sdm->data);CHKERRQ(ierr);
39   if (oldsdm->data) {ierr = PetscMemcpy(sdm->data,oldsdm->data,sizeof(DMTS_DA));CHKERRQ(ierr);}
40   PetscFunctionReturn(0);
41 }
42 
43 #undef __FUNCT__
44 #define __FUNCT__ "DMDATSGetContext"
45 static PetscErrorCode DMDATSGetContext(DM dm,DMTS sdm,DMTS_DA **dmdats)
46 {
47   PetscErrorCode ierr;
48 
49   PetscFunctionBegin;
50   *dmdats = NULL;
51   if (!sdm->data) {
52     ierr = PetscNewLog(dm,(DMTS_DA**)&sdm->data);CHKERRQ(ierr);
53     sdm->ops->destroy   = DMTSDestroy_DMDA;
54     sdm->ops->duplicate = DMTSDuplicate_DMDA;
55   }
56   *dmdats = (DMTS_DA*)sdm->data;
57   PetscFunctionReturn(0);
58 }
59 
60 #undef __FUNCT__
61 #define __FUNCT__ "TSComputeIFunction_DMDA"
62 /*
63   This function should eventually replace:
64     DMDAComputeFunction() and DMDAComputeFunction1()
65  */
66 static PetscErrorCode TSComputeIFunction_DMDA(TS ts,PetscReal ptime,Vec X,Vec Xdot,Vec F,void *ctx)
67 {
68   PetscErrorCode ierr;
69   DM             dm;
70   DMTS_DA        *dmdats = (DMTS_DA*)ctx;
71   DMDALocalInfo  info;
72   Vec            Xloc;
73   void           *x,*f,*xdot;
74 
75   PetscFunctionBegin;
76   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
77   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
78   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
79   if (!dmdats->ifunctionlocal) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Corrupt context");
80   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
81   ierr = DMGetLocalVector(dm,&Xloc);CHKERRQ(ierr);
82   ierr = DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr);
83   ierr = DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr);
84   ierr = DMDAGetLocalInfo(dm,&info);CHKERRQ(ierr);
85   ierr = DMDAVecGetArray(dm,Xloc,&x);CHKERRQ(ierr);
86   ierr = DMDAVecGetArray(dm,Xdot,&xdot);CHKERRQ(ierr);
87   switch (dmdats->ifunctionlocalimode) {
88   case INSERT_VALUES: {
89     ierr = DMDAVecGetArray(dm,F,&f);CHKERRQ(ierr);
90     CHKMEMQ;
91     ierr = (*dmdats->ifunctionlocal)(&info,ptime,x,xdot,f,dmdats->ifunctionlocalctx);CHKERRQ(ierr);
92     CHKMEMQ;
93     ierr = DMDAVecRestoreArray(dm,F,&f);CHKERRQ(ierr);
94   } break;
95   case ADD_VALUES: {
96     Vec Floc;
97     ierr = DMGetLocalVector(dm,&Floc);CHKERRQ(ierr);
98     ierr = VecZeroEntries(Floc);CHKERRQ(ierr);
99     ierr = DMDAVecGetArray(dm,Floc,&f);CHKERRQ(ierr);
100     CHKMEMQ;
101     ierr = (*dmdats->ifunctionlocal)(&info,ptime,x,xdot,f,dmdats->ifunctionlocalctx);CHKERRQ(ierr);
102     CHKMEMQ;
103     ierr = DMDAVecRestoreArray(dm,Floc,&f);CHKERRQ(ierr);
104     ierr = VecZeroEntries(F);CHKERRQ(ierr);
105     ierr = DMLocalToGlobalBegin(dm,Floc,ADD_VALUES,F);CHKERRQ(ierr);
106     ierr = DMLocalToGlobalEnd(dm,Floc,ADD_VALUES,F);CHKERRQ(ierr);
107     ierr = DMRestoreLocalVector(dm,&Floc);CHKERRQ(ierr);
108   } break;
109   default: SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_INCOMP,"Cannot use imode=%d",(int)dmdats->ifunctionlocalimode);
110   }
111   ierr = DMDAVecRestoreArray(dm,Xloc,&x);CHKERRQ(ierr);
112   ierr = DMRestoreLocalVector(dm,&Xloc);CHKERRQ(ierr);
113   ierr = DMDAVecRestoreArray(dm,Xdot,&xdot);CHKERRQ(ierr);
114   PetscFunctionReturn(0);
115 }
116 
117 #undef __FUNCT__
118 #define __FUNCT__ "TSComputeIJacobian_DMDA"
119 static PetscErrorCode TSComputeIJacobian_DMDA(TS ts,PetscReal ptime,Vec X,Vec Xdot,PetscReal shift,Mat *A,Mat *B,MatStructure *mstr,void *ctx)
120 {
121   PetscErrorCode ierr;
122   DM             dm;
123   DMTS_DA        *dmdats = (DMTS_DA*)ctx;
124   DMDALocalInfo  info;
125   Vec            Xloc;
126   void           *x,*xdot;
127 
128   PetscFunctionBegin;
129   if (!dmdats->ifunctionlocal) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Corrupt context");
130   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
131 
132   if (dmdats->ijacobianlocal) {
133     ierr = DMGetLocalVector(dm,&Xloc);CHKERRQ(ierr);
134     ierr = DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr);
135     ierr = DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr);
136     ierr = DMDAGetLocalInfo(dm,&info);CHKERRQ(ierr);
137     ierr = DMDAVecGetArray(dm,Xloc,&x);CHKERRQ(ierr);
138     ierr = DMDAVecGetArray(dm,Xdot,&xdot);CHKERRQ(ierr);
139     CHKMEMQ;
140     ierr = (*dmdats->ijacobianlocal)(&info,ptime,x,xdot,shift,*A,*B,mstr,dmdats->ijacobianlocalctx);CHKERRQ(ierr);
141     CHKMEMQ;
142     ierr = DMDAVecRestoreArray(dm,Xloc,&x);CHKERRQ(ierr);
143     ierr = DMDAVecRestoreArray(dm,Xdot,&xdot);CHKERRQ(ierr);
144     ierr = DMRestoreLocalVector(dm,&Xloc);CHKERRQ(ierr);
145   } else SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"TSComputeIJacobian_DMDA() called without calling DMDATSSetIJacobian()");
146   /* This will be redundant if the user called both, but it's too common to forget. */
147   if (*A != *B) {
148     ierr = MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
149     ierr = MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
150   }
151   PetscFunctionReturn(0);
152 }
153 
154 #undef __FUNCT__
155 #define __FUNCT__ "TSComputeRHSFunction_DMDA"
156 /*
157   This function should eventually replace:
158     DMDAComputeFunction() and DMDAComputeFunction1()
159  */
160 static PetscErrorCode TSComputeRHSFunction_DMDA(TS ts,PetscReal ptime,Vec X,Vec F,void *ctx)
161 {
162   PetscErrorCode ierr;
163   DM             dm;
164   DMTS_DA        *dmdats = (DMTS_DA*)ctx;
165   DMDALocalInfo  info;
166   Vec            Xloc;
167   void           *x,*f;
168 
169   PetscFunctionBegin;
170   PetscValidHeaderSpecific(ts,TS_CLASSID,1);
171   PetscValidHeaderSpecific(X,VEC_CLASSID,2);
172   PetscValidHeaderSpecific(F,VEC_CLASSID,3);
173   if (!dmdats->rhsfunctionlocal) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Corrupt context");
174   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
175   ierr = DMGetLocalVector(dm,&Xloc);CHKERRQ(ierr);
176   ierr = DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr);
177   ierr = DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr);
178   ierr = DMDAGetLocalInfo(dm,&info);CHKERRQ(ierr);
179   ierr = DMDAVecGetArray(dm,Xloc,&x);CHKERRQ(ierr);
180   switch (dmdats->rhsfunctionlocalimode) {
181   case INSERT_VALUES: {
182     ierr = DMDAVecGetArray(dm,F,&f);CHKERRQ(ierr);
183     CHKMEMQ;
184     ierr = (*dmdats->rhsfunctionlocal)(&info,ptime,x,f,dmdats->rhsfunctionlocalctx);CHKERRQ(ierr);
185     CHKMEMQ;
186     ierr = DMDAVecRestoreArray(dm,F,&f);CHKERRQ(ierr);
187   } break;
188   case ADD_VALUES: {
189     Vec Floc;
190     ierr = DMGetLocalVector(dm,&Floc);CHKERRQ(ierr);
191     ierr = VecZeroEntries(Floc);CHKERRQ(ierr);
192     ierr = DMDAVecGetArray(dm,Floc,&f);CHKERRQ(ierr);
193     CHKMEMQ;
194     ierr = (*dmdats->rhsfunctionlocal)(&info,ptime,x,f,dmdats->rhsfunctionlocalctx);CHKERRQ(ierr);
195     CHKMEMQ;
196     ierr = DMDAVecRestoreArray(dm,Floc,&f);CHKERRQ(ierr);
197     ierr = VecZeroEntries(F);CHKERRQ(ierr);
198     ierr = DMLocalToGlobalBegin(dm,Floc,ADD_VALUES,F);CHKERRQ(ierr);
199     ierr = DMLocalToGlobalEnd(dm,Floc,ADD_VALUES,F);CHKERRQ(ierr);
200     ierr = DMRestoreLocalVector(dm,&Floc);CHKERRQ(ierr);
201   } break;
202   default: SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_INCOMP,"Cannot use imode=%d",(int)dmdats->rhsfunctionlocalimode);
203   }
204   ierr = DMDAVecRestoreArray(dm,Xloc,&x);CHKERRQ(ierr);
205   ierr = DMRestoreLocalVector(dm,&Xloc);CHKERRQ(ierr);
206   PetscFunctionReturn(0);
207 }
208 
209 #undef __FUNCT__
210 #define __FUNCT__ "TSComputeRHSJacobian_DMDA"
211 static PetscErrorCode TSComputeRHSJacobian_DMDA(TS ts,PetscReal ptime,Vec X,Mat *A,Mat *B,MatStructure *mstr,void *ctx)
212 {
213   PetscErrorCode ierr;
214   DM             dm;
215   DMTS_DA        *dmdats = (DMTS_DA*)ctx;
216   DMDALocalInfo  info;
217   Vec            Xloc;
218   void           *x;
219 
220   PetscFunctionBegin;
221   if (!dmdats->rhsfunctionlocal) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Corrupt context");
222   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
223 
224   if (dmdats->rhsjacobianlocal) {
225     ierr = DMGetLocalVector(dm,&Xloc);CHKERRQ(ierr);
226     ierr = DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr);
227     ierr = DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr);
228     ierr = DMDAGetLocalInfo(dm,&info);CHKERRQ(ierr);
229     ierr = DMDAVecGetArray(dm,Xloc,&x);CHKERRQ(ierr);
230     CHKMEMQ;
231     ierr = (*dmdats->rhsjacobianlocal)(&info,ptime,x,*A,*B,mstr,dmdats->rhsjacobianlocalctx);CHKERRQ(ierr);
232     CHKMEMQ;
233     ierr = DMDAVecRestoreArray(dm,Xloc,&x);CHKERRQ(ierr);
234     ierr = DMRestoreLocalVector(dm,&Xloc);CHKERRQ(ierr);
235   } else SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"TSComputeRHSJacobian_DMDA() called without calling DMDATSSetRHSJacobian()");
236   /* This will be redundant if the user called both, but it's too common to forget. */
237   if (*A != *B) {
238     ierr = MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
239     ierr = MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
240   }
241   PetscFunctionReturn(0);
242 }
243 
244 
245 #undef __FUNCT__
246 #define __FUNCT__ "DMDATSSetRHSFunctionLocal"
247 /*@C
248    DMDATSSetRHSFunctionLocal - set a local residual evaluation function
249 
250    Logically Collective
251 
252    Input Arguments:
253 +  dm - DM to associate callback with
254 .  imode - insert mode for the residual
255 .  func - local residual evaluation
256 -  ctx - optional context for local residual evaluation
257 
258    Calling sequence for func:
259 
260 $ func(DMDALocalInfo info,PetscReal t,void *x,void *f,void *ctx)
261 
262 +  info - DMDALocalInfo defining the subdomain to evaluate the residual on
263 .  t - time at which to evaluate residual
264 .  x - array of local state information
265 .  f - output array of local residual information
266 -  ctx - optional user context
267 
268    Level: beginner
269 
270 .seealso: DMTSSetRHSFunction(), DMDATSSetRHSJacobianLocal(), DMDASNESSetFunctionLocal()
271 @*/
272 PetscErrorCode DMDATSSetRHSFunctionLocal(DM dm,InsertMode imode,DMDATSRHSFunctionLocal func,void *ctx)
273 {
274   PetscErrorCode ierr;
275   DMTS           sdm;
276   DMTS_DA        *dmdats;
277 
278   PetscFunctionBegin;
279   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
280   ierr = DMGetDMTSWrite(dm,&sdm);CHKERRQ(ierr);
281   ierr = DMDATSGetContext(dm,sdm,&dmdats);CHKERRQ(ierr);
282   dmdats->rhsfunctionlocalimode = imode;
283   dmdats->rhsfunctionlocal      = func;
284   dmdats->rhsfunctionlocalctx   = ctx;
285   ierr = DMTSSetRHSFunction(dm,TSComputeRHSFunction_DMDA,dmdats);CHKERRQ(ierr);
286   PetscFunctionReturn(0);
287 }
288 
289 #undef __FUNCT__
290 #define __FUNCT__ "DMDATSSetRHSJacobianLocal"
291 /*@C
292    DMDATSSetRHSJacobianLocal - set a local residual evaluation function
293 
294    Logically Collective
295 
296    Input Arguments:
297 +  dm    - DM to associate callback with
298 .  func  - local RHS Jacobian evaluation routine
299 -  ctx   - optional context for local jacobian evaluation
300 
301    Calling sequence for func:
302 
303 $ func(DMDALocalInfo* info,PetscReal t,void* x,Mat J,Mat B,MatStructure *flg,void *ctx);
304 
305 +  info - DMDALocalInfo defining the subdomain to evaluate the residual on
306 .  t    - time at which to evaluate residual
307 .  x    - array of local state information
308 .  J    - Jacobian matrix
309 .  B    - preconditioner matrix; often same as J
310 .  flg  - flag indicating information about the preconditioner matrix structure (same as flag in KSPSetOperators())
311 -  ctx  - optional context passed above
312 
313    Level: beginner
314 
315 .seealso: DMTSSetRHSJacobian(), DMDATSSetRHSFunctionLocal(), DMDASNESSetJacobianLocal()
316 @*/
317 PetscErrorCode DMDATSSetRHSJacobianLocal(DM dm,DMDATSRHSJacobianLocal func,void *ctx)
318 {
319   PetscErrorCode ierr;
320   DMTS           sdm;
321   DMTS_DA        *dmdats;
322 
323   PetscFunctionBegin;
324   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
325   ierr = DMGetDMTSWrite(dm,&sdm);CHKERRQ(ierr);
326   ierr = DMDATSGetContext(dm,sdm,&dmdats);CHKERRQ(ierr);
327   dmdats->rhsjacobianlocal    = func;
328   dmdats->rhsjacobianlocalctx = ctx;
329   ierr = DMTSSetRHSJacobian(dm,TSComputeRHSJacobian_DMDA,dmdats);CHKERRQ(ierr);
330   PetscFunctionReturn(0);
331 }
332 
333 
334 #undef __FUNCT__
335 #define __FUNCT__ "DMDATSSetIFunctionLocal"
336 /*@C
337    DMDATSSetIFunctionLocal - set a local residual evaluation function
338 
339    Logically Collective
340 
341    Input Arguments:
342 +  dm   - DM to associate callback with
343 .  func - local residual evaluation
344 -  ctx  - optional context for local residual evaluation
345 
346    Calling sequence for func:
347 +  info - DMDALocalInfo defining the subdomain to evaluate the residual on
348 .  t    - time at which to evaluate residual
349 .  x    - array of local state information
350 .  xdot - array of local time derivative information
351 .  f    - output array of local function evaluation information
352 -  ctx - optional context passed above
353 
354    Level: beginner
355 
356 .seealso: DMTSSetIFunction(), DMDATSSetIJacobianLocal(), DMDASNESSetFunctionLocal()
357 @*/
358 PetscErrorCode DMDATSSetIFunctionLocal(DM dm,InsertMode imode,DMDATSIFunctionLocal func,void *ctx)
359 {
360   PetscErrorCode ierr;
361   DMTS           sdm;
362   DMTS_DA        *dmdats;
363 
364   PetscFunctionBegin;
365   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
366   ierr = DMGetDMTSWrite(dm,&sdm);CHKERRQ(ierr);
367   ierr = DMDATSGetContext(dm,sdm,&dmdats);CHKERRQ(ierr);
368   dmdats->ifunctionlocalimode = imode;
369   dmdats->ifunctionlocal      = func;
370   dmdats->ifunctionlocalctx   = ctx;
371   ierr = DMTSSetIFunction(dm,TSComputeIFunction_DMDA,dmdats);CHKERRQ(ierr);
372   PetscFunctionReturn(0);
373 }
374 
375 #undef __FUNCT__
376 #define __FUNCT__ "DMDATSSetIJacobianLocal"
377 /*@C
378    DMDATSSetIJacobianLocal - set a local residual evaluation function
379 
380    Logically Collective
381 
382    Input Arguments:
383 +  dm   - DM to associate callback with
384 .  func - local residual evaluation
385 -  ctx   - optional context for local residual evaluation
386 
387    Calling sequence for func:
388 
389 $ func(DMDALocalInfo* info,PetscReal t,void* x,void *xdot,Mat J,Mat B,MatStructure *flg,void *ctx);
390 
391 +  info - DMDALocalInfo defining the subdomain to evaluate the residual on
392 .  t    - time at which to evaluate the jacobian
393 .  x    - array of local state information
394 .  xdot - time derivative at this state
395 .  J    - Jacobian matrix
396 .  B    - preconditioner matrix; often same as J
397 .  flg  - flag indicating information about the preconditioner matrix structure (same as flag in KSPSetOperators())
398 -  ctx  - optional context passed above
399 
400    Level: beginner
401 
402 .seealso: DMTSSetJacobian(), DMDATSSetIFunctionLocal(), DMDASNESSetJacobianLocal()
403 @*/
404 PetscErrorCode DMDATSSetIJacobianLocal(DM dm,DMDATSIJacobianLocal func,void *ctx)
405 {
406   PetscErrorCode ierr;
407   DMTS           sdm;
408   DMTS_DA        *dmdats;
409 
410   PetscFunctionBegin;
411   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
412   ierr = DMGetDMTSWrite(dm,&sdm);CHKERRQ(ierr);
413   ierr = DMDATSGetContext(dm,sdm,&dmdats);CHKERRQ(ierr);
414   dmdats->ijacobianlocal    = func;
415   dmdats->ijacobianlocalctx = ctx;
416   ierr = DMTSSetIJacobian(dm,TSComputeIJacobian_DMDA,dmdats);CHKERRQ(ierr);
417   PetscFunctionReturn(0);
418 }
419 
420 #undef __FUNCT__
421 #define __FUNCT__ "TSMonitorDMDARayDestroy"
422 PetscErrorCode TSMonitorDMDARayDestroy(void **mctx)
423 {
424   TSMonitorDMDARayCtx *rayctx = (TSMonitorDMDARayCtx *) *mctx;
425   PetscErrorCode       ierr;
426 
427   PetscFunctionBegin;
428   if (rayctx->lgctx) {ierr = TSMonitorLGCtxDestroy(&rayctx->lgctx);CHKERRQ(ierr);}
429   ierr = VecDestroy(&rayctx->ray);CHKERRQ(ierr);
430   ierr = VecScatterDestroy(&rayctx->scatter);CHKERRQ(ierr);
431   ierr = PetscViewerDestroy(&rayctx->viewer);CHKERRQ(ierr);
432   ierr = PetscFree(rayctx);CHKERRQ(ierr);
433   PetscFunctionReturn(0);
434 }
435 
436 #undef __FUNCT__
437 #define __FUNCT__ "TSMonitorDMDARay"
438 PetscErrorCode TSMonitorDMDARay(TS ts,PetscInt steps,PetscReal time,Vec u,void *mctx)
439 {
440   TSMonitorDMDARayCtx *rayctx = (TSMonitorDMDARayCtx*)mctx;
441   Vec                 solution;
442   PetscErrorCode      ierr;
443 
444   PetscFunctionBegin;
445   ierr = TSGetSolution(ts,&solution);CHKERRQ(ierr);
446   ierr = VecScatterBegin(rayctx->scatter,solution,rayctx->ray,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
447   ierr = VecScatterEnd(rayctx->scatter,solution,rayctx->ray,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
448   if (rayctx->viewer) {
449     ierr = VecView(rayctx->ray,rayctx->viewer);CHKERRQ(ierr);
450   }
451   PetscFunctionReturn(0);
452 }
453 
454 #undef __FUNCT__
455 #define __FUNCT__ "TSMonitorLGDMDARay"
456 PetscErrorCode  TSMonitorLGDMDARay(TS ts, PetscInt step, PetscReal ptime, Vec u, void *ctx)
457 {
458   TSMonitorDMDARayCtx *rayctx = (TSMonitorDMDARayCtx *) ctx;
459   TSMonitorLGCtx       lgctx  = (TSMonitorLGCtx) rayctx->lgctx;
460   Vec                  v      = rayctx->ray;
461   const PetscScalar   *a;
462   PetscInt             dim;
463   PetscErrorCode       ierr;
464 
465   PetscFunctionBegin;
466   ierr = VecScatterBegin(rayctx->scatter, u, v, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr);
467   ierr = VecScatterEnd(rayctx->scatter, u, v, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr);
468   if (!step) {
469     PetscDrawAxis axis;
470 
471     ierr = PetscDrawLGGetAxis(lgctx->lg, &axis);CHKERRQ(ierr);
472     ierr = PetscDrawAxisSetLabels(axis, "Solution Ray as function of time", "Time", "Solution");CHKERRQ(ierr);
473     ierr = VecGetLocalSize(rayctx->ray, &dim);CHKERRQ(ierr);
474     ierr = PetscDrawLGSetDimension(lgctx->lg, dim);CHKERRQ(ierr);
475     ierr = PetscDrawLGReset(lgctx->lg);CHKERRQ(ierr);
476   }
477   ierr = VecGetArrayRead(v, &a);CHKERRQ(ierr);
478 #if defined(PETSC_USE_COMPLEX)
479   {
480     PetscReal *areal;
481     PetscInt   i,n;
482     ierr = VecGetLocalSize(v, &n);CHKERRQ(ierr);
483     ierr = PetscMalloc1(n, &areal);CHKERRQ(ierr);
484     for (i = 0; i < n; ++i) areal[i] = PetscRealPart(a[i]);
485     ierr = PetscDrawLGAddCommonPoint(lgctx->lg, ptime, areal);CHKERRQ(ierr);
486     ierr = PetscFree(areal);CHKERRQ(ierr);
487   }
488 #else
489   ierr = PetscDrawLGAddCommonPoint(lgctx->lg, ptime, a);CHKERRQ(ierr);
490 #endif
491   ierr = VecRestoreArrayRead(v, &a);CHKERRQ(ierr);
492   if (((lgctx->howoften > 0) && (!(step % lgctx->howoften))) || ((lgctx->howoften == -1) && ts->reason)) {
493     ierr = PetscDrawLGDraw(lgctx->lg);CHKERRQ(ierr);
494   }
495   PetscFunctionReturn(0);
496 }
497