xref: /petsc/src/ts/interface/tseig.c (revision f9c1d6ab8e7393bf59844353079a9f288b132623)
1 #define PETSC_DESIRE_COMPLEX
2 #include <petsc-private/tsimpl.h>        /*I "petscts.h"  I*/
3 
4 /* ------------------------------------------------------------------------*/
5 struct _n_TSMonitorSPEigCtx {
6   PetscDrawSP drawsp;
7   KSP         ksp;
8   PetscInt    howoften;  /* when > 0 uses step % howoften, when negative only final solution plotted */
9   PetscBool   computeexplicitly;
10   MPI_Comm    comm;
11   PetscRandom rand;
12   PetscScalar shift;
13   PetscReal   xmin,xmax,ymin,ymax;
14 };
15 
16 
17 #undef __FUNCT__
18 #define __FUNCT__ "TSMonitorSPEigCtxCreate"
19 /*@C
20    TSMonitorSPEigCtxCreate - Creates a context for use with TS to monitor the eigenvalues of the linearized operator
21 
22    Collective on TS
23 
24    Input Parameters:
25 +  host - the X display to open, or null for the local machine
26 .  label - the title to put in the title bar
27 .  x, y - the screen coordinates of the upper left coordinate of the window
28 .  m, n - the screen width and height in pixels
29 -  howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
30 
31    Output Parameter:
32 .  ctx - the context
33 
34    Options Database Key:
35 .  -ts_monitor_sp_eig - plot egienvalues of linearized right hand side
36 
37    Notes:
38    Use TSMonitorSPEigCtxDestroy() to destroy.
39 
40    Currently only works if the Jacobian is provided explicitly.
41 
42    Currently only works for ODEs u_t - F(t,u) = 0; that is with no mass matrix.
43 
44    Level: intermediate
45 
46 .keywords: TS, monitor, line graph, residual, seealso
47 
48 .seealso: TSMonitorSPEigTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError()
49 
50 @*/
51 PetscErrorCode  TSMonitorSPEigCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorSPEigCtx *ctx)
52 {
53   PetscDraw      win;
54   PetscErrorCode ierr;
55   PC             pc;
56 
57   PetscFunctionBegin;
58   ierr = PetscNew(struct _n_TSMonitorSPEigCtx,ctx);CHKERRQ(ierr);
59   ierr = PetscRandomCreate(comm,&(*ctx)->rand);CHKERRQ(ierr);
60   ierr = PetscRandomSetFromOptions((*ctx)->rand);CHKERRQ(ierr);
61   ierr = PetscDrawCreate(comm,host,label,x,y,m,n,&win);CHKERRQ(ierr);
62   ierr = PetscDrawSetFromOptions(win);CHKERRQ(ierr);
63   ierr = PetscDrawSPCreate(win,1,&(*ctx)->drawsp);CHKERRQ(ierr);
64   ierr = KSPCreate(comm,&(*ctx)->ksp);CHKERRQ(ierr);
65   ierr = KSPSetOptionsPrefix((*ctx)->ksp,"ts_monitor_sp_eig_");CHKERRQ(ierr); /* this is wrong, used use also prefix from the TS */
66   ierr = KSPSetType((*ctx)->ksp,KSPGMRES);CHKERRQ(ierr);
67   ierr = KSPGMRESSetRestart((*ctx)->ksp,200);CHKERRQ(ierr);
68   ierr = KSPSetTolerances((*ctx)->ksp,1.e-10,PETSC_DEFAULT,PETSC_DEFAULT,200);CHKERRQ(ierr);
69   ierr = KSPSetComputeSingularValues((*ctx)->ksp,PETSC_TRUE);CHKERRQ(ierr);
70   ierr = KSPSetFromOptions((*ctx)->ksp);CHKERRQ(ierr);
71   ierr = KSPGetPC((*ctx)->ksp,&pc);CHKERRQ(ierr);
72   ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr);
73   (*ctx)->howoften          = howoften;
74   (*ctx)->computeexplicitly = PETSC_FALSE;
75   ierr = PetscOptionsGetBool(PETSC_NULL,"-ts_monitor_sp_eig_explicitly",&(*ctx)->computeexplicitly,PETSC_NULL);CHKERRQ(ierr);
76   (*ctx)->shift             = 0.0;
77   ierr = PetscOptionsGetScalar(PETSC_NULL,"-ts_monitor_sp_eig_shift",&(*ctx)->shift,PETSC_NULL);CHKERRQ(ierr);
78   (*ctx)->comm              = comm;
79   (*ctx)->xmin = -2.1;
80   (*ctx)->xmax = 1.1;
81   (*ctx)->ymin = -1.1;
82   (*ctx)->ymax = 1.1;
83   PetscFunctionReturn(0);
84 }
85 
86 #undef __FUNCT__
87 #define __FUNCT__ "TSLinearStabilityIndicator"
88 static PetscErrorCode TSLinearStabilityIndicator(TS  ts, PetscReal xr,PetscReal xi,PetscBool *flg)
89 {
90   PetscErrorCode ierr;
91   PetscReal      yr,yi;
92 
93   PetscFunctionBegin;
94   ierr = TSComputeLinearStability(ts,xr,xi,&yr,&yi);CHKERRQ(ierr);
95   if ((yr*yr + yi*yi) <= 1.0) *flg = PETSC_TRUE;
96   else *flg = PETSC_FALSE;
97   PetscFunctionReturn(0);
98 }
99 
100 #undef __FUNCT__
101 #define __FUNCT__ "TSMonitorSPEig"
102 PetscErrorCode TSMonitorSPEig(TS ts,PetscInt step,PetscReal ptime,Vec v,void *monctx)
103 {
104   TSMonitorSPEigCtx ctx = (TSMonitorSPEigCtx) monctx;
105   PetscErrorCode    ierr;
106   KSP               ksp = ctx->ksp;
107   PetscInt          n,N,nits,neig,i,its = 200;
108   PetscReal         *r,*c;
109   PetscDrawSP       drawsp = ctx->drawsp;
110   MatStructure      structure;
111   Mat               A,B;
112   Vec               xdot;
113   SNES              snes;
114 
115   PetscFunctionBegin;
116   if (!step) PetscFunctionReturn(0);
117   if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && (step == -1))){
118     ierr = VecDuplicate(v,&xdot);CHKERRQ(ierr);
119     ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr);
120     ierr = SNESGetJacobian(snes,&A,&B,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
121     ierr = MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,&B);CHKERRQ(ierr);
122     /*
123        This doesn't work because methods keep and use internal information about the shift so it
124        seems we would need code for each method to trick the correct Jacobian in being computed.
125     ts->time_step = PETSC_MAX_REAL;
126     ierr = SNESComputeJacobian(snes,v,&A,&B,&structure);CHKERRQ(ierr);
127     */
128     ierr = TSComputeIJacobian(ts,ptime,v,xdot,0.0,&B,&B,&structure,PETSC_FALSE);CHKERRQ(ierr);
129     ierr = MatScale(B,-1.0*ts->time_step);CHKERRQ(ierr);
130     ierr = MatShift(B,ctx->shift);CHKERRQ(ierr);
131 
132     ierr = KSPSetOperators(ksp,B,B,structure);CHKERRQ(ierr);
133     ierr = VecGetSize(v,&n);CHKERRQ(ierr);
134     if (n < 200) its = n;
135     ierr = KSPSetTolerances(ksp,1.e-10,PETSC_DEFAULT,PETSC_DEFAULT,its);CHKERRQ(ierr);
136     ierr = VecSetRandom(xdot,ctx->rand);CHKERRQ(ierr);
137     ierr = KSPSolve(ksp,xdot,xdot);CHKERRQ(ierr);
138     ierr = VecDestroy(&xdot);CHKERRQ(ierr);
139     ierr = KSPGetIterationNumber(ksp,&nits);CHKERRQ(ierr);
140     N = nits+2;
141 
142     if (nits) {
143       PetscDraw     draw;
144       PetscReal     pause;
145       PetscDrawAxis axis;
146       PetscReal     xmin,xmax,ymin,ymax;
147 
148       ierr = PetscDrawSPReset(drawsp);CHKERRQ(ierr);
149       ierr = PetscDrawSPSetLimits(drawsp,ctx->xmin,ctx->xmax,ctx->ymin,ctx->ymax);CHKERRQ(ierr);
150       ierr = PetscMalloc2(PetscMax(n,N),PetscReal,&r,PetscMax(n,N),PetscReal,&c);CHKERRQ(ierr);
151       if (ctx->computeexplicitly) {
152         ierr = KSPComputeEigenvaluesExplicitly(ksp,n,r,c);CHKERRQ(ierr);
153         neig = n;
154       } else {
155         ierr = KSPComputeEigenvalues(ksp,N,r,c,&neig);CHKERRQ(ierr);
156       }
157       for (i=0; i<neig; i++) {
158         r[i] -= PetscAbsScalar(ctx->shift);
159         ierr = PetscPrintf(ctx->comm,"%g + %g i\n",r[i],c[i]);CHKERRQ(ierr);
160         ierr = PetscDrawSPAddPoint(drawsp,r+i,c+i);CHKERRQ(ierr);
161       }
162       ierr = PetscFree2(r,c);CHKERRQ(ierr);
163       ierr = PetscDrawSPGetDraw(drawsp,&draw);CHKERRQ(ierr);
164       ierr = PetscDrawGetPause(draw,&pause);CHKERRQ(ierr);
165       ierr = PetscDrawSetPause(draw,0.0);CHKERRQ(ierr);
166       ierr = PetscDrawSPDraw(drawsp,PETSC_TRUE);CHKERRQ(ierr);
167       ierr = PetscDrawSetPause(draw,pause);CHKERRQ(ierr);
168 
169       if (ts->ops->linearstability) {
170         ierr = PetscDrawSPGetAxis(drawsp,&axis);CHKERRQ(ierr);
171         ierr = PetscDrawAxisGetLimits(axis,&xmin,&xmax,&ymin,&ymax);CHKERRQ(ierr);
172         ierr = PetscDrawIndicatorFunction(draw,xmin,xmax,ymin,ymax,PETSC_DRAW_CYAN,(PetscErrorCode (*)(void*,PetscReal,PetscReal,PetscBool*))TSLinearStabilityIndicator,ts);CHKERRQ(ierr);
173         ierr = PetscDrawSPDraw(drawsp,PETSC_FALSE);CHKERRQ(ierr);
174       }
175     }
176     ierr = MatDestroy(&B);CHKERRQ(ierr);
177   }
178   PetscFunctionReturn(0);
179 }
180 
181 #undef __FUNCT__
182 #define __FUNCT__ "TSMonitorSPEigCtxDestroy"
183 /*@C
184    TSMonitorSPEigCtxDestroy - Destroys a scatter plot context that was created with TSMonitorSPEigCtxCreate().
185 
186    Collective on TSMonitorSPEigCtx
187 
188    Input Parameter:
189 .  ctx - the monitor context
190 
191    Level: intermediate
192 
193 .keywords: TS, monitor, line graph, destroy
194 
195 .seealso: TSMonitorSPEigCtxCreate(),  TSMonitorSet(), TSMonitorSPEig();
196 @*/
197 PetscErrorCode  TSMonitorSPEigCtxDestroy(TSMonitorSPEigCtx *ctx)
198 {
199   PetscDraw      draw;
200   PetscErrorCode ierr;
201 
202   PetscFunctionBegin;
203   ierr = PetscDrawSPGetDraw((*ctx)->drawsp,&draw);CHKERRQ(ierr);
204   ierr = PetscDrawDestroy(&draw);CHKERRQ(ierr);
205   ierr = PetscDrawSPDestroy(&(*ctx)->drawsp);CHKERRQ(ierr);
206   ierr = KSPDestroy(&(*ctx)->ksp);CHKERRQ(ierr);
207   ierr = PetscRandomDestroy(&(*ctx)->rand);CHKERRQ(ierr);
208   ierr = PetscFree(*ctx);CHKERRQ(ierr);
209   PetscFunctionReturn(0);
210 }
211 
212 
213 
214