xref: /petsc/src/ts/tests/ex4.c (revision 5f80ce2ab25dff0f4601e710601cbbcecf323266)
1c4762a1bSJed Brown /*
2c4762a1bSJed Brown        The Problem:
3c4762a1bSJed Brown            Solve the convection-diffusion equation:
4c4762a1bSJed Brown 
5c4762a1bSJed Brown              u_t+a*(u_x+u_y)=epsilon*(u_xx+u_yy)
6c4762a1bSJed Brown              u=0   at x=0, y=0
7c4762a1bSJed Brown              u_x=0 at x=1
8c4762a1bSJed Brown              u_y=0 at y=1
9c4762a1bSJed Brown              u = exp(-20.0*(pow(x-0.5,2.0)+pow(y-0.5,2.0))) at t=0
10c4762a1bSJed Brown 
11c4762a1bSJed Brown        This program tests the routine of computing the Jacobian by the
12c4762a1bSJed Brown        finite difference method as well as PETSc.
13c4762a1bSJed Brown 
14c4762a1bSJed Brown */
15c4762a1bSJed Brown 
16c4762a1bSJed Brown static char help[] = "Solve the convection-diffusion equation. \n\n";
17c4762a1bSJed Brown 
18c4762a1bSJed Brown #include <petscts.h>
19c4762a1bSJed Brown 
20c4762a1bSJed Brown typedef struct
21c4762a1bSJed Brown {
22c4762a1bSJed Brown   PetscInt  m;          /* the number of mesh points in x-direction */
23c4762a1bSJed Brown   PetscInt  n;          /* the number of mesh points in y-direction */
24c4762a1bSJed Brown   PetscReal dx;         /* the grid space in x-direction */
25c4762a1bSJed Brown   PetscReal dy;         /* the grid space in y-direction */
26c4762a1bSJed Brown   PetscReal a;          /* the convection coefficient    */
27c4762a1bSJed Brown   PetscReal epsilon;    /* the diffusion coefficient     */
28c4762a1bSJed Brown   PetscReal tfinal;
29c4762a1bSJed Brown } Data;
30c4762a1bSJed Brown 
31c4762a1bSJed Brown extern PetscErrorCode Monitor(TS,PetscInt,PetscReal,Vec,void*);
32c4762a1bSJed Brown extern PetscErrorCode Initial(Vec,void*);
33c4762a1bSJed Brown extern PetscErrorCode RHSFunction(TS,PetscReal,Vec,Vec,void*);
34c4762a1bSJed Brown extern PetscErrorCode RHSJacobian(TS,PetscReal,Vec,Mat,Mat,void*);
35c4762a1bSJed Brown extern PetscErrorCode PostStep(TS);
36c4762a1bSJed Brown 
37c4762a1bSJed Brown int main(int argc,char **argv)
38c4762a1bSJed Brown {
39c4762a1bSJed Brown   PetscErrorCode ierr;
40c4762a1bSJed Brown   PetscInt       time_steps=100,iout,NOUT=1;
41c4762a1bSJed Brown   Vec            global;
42c4762a1bSJed Brown   PetscReal      dt,ftime,ftime_original;
43c4762a1bSJed Brown   TS             ts;
44c4762a1bSJed Brown   PetscViewer    viewfile;
45c4762a1bSJed Brown   Mat            J = 0;
46c4762a1bSJed Brown   Vec            x;
47c4762a1bSJed Brown   Data           data;
48c4762a1bSJed Brown   PetscInt       mn;
49c4762a1bSJed Brown   PetscBool      flg;
50c4762a1bSJed Brown   MatColoring    mc;
51c4762a1bSJed Brown   ISColoring     iscoloring;
52c4762a1bSJed Brown   MatFDColoring  matfdcoloring        = 0;
53c4762a1bSJed Brown   PetscBool      fd_jacobian_coloring = PETSC_FALSE;
54c4762a1bSJed Brown   SNES           snes;
55c4762a1bSJed Brown   KSP            ksp;
56c4762a1bSJed Brown   PC             pc;
57c4762a1bSJed Brown 
58c4762a1bSJed Brown   ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr;
59c4762a1bSJed Brown 
60c4762a1bSJed Brown   /* set data */
61c4762a1bSJed Brown   data.m       = 9;
62c4762a1bSJed Brown   data.n       = 9;
63c4762a1bSJed Brown   data.a       = 1.0;
64c4762a1bSJed Brown   data.epsilon = 0.1;
65c4762a1bSJed Brown   data.dx      = 1.0/(data.m+1.0);
66c4762a1bSJed Brown   data.dy      = 1.0/(data.n+1.0);
67c4762a1bSJed Brown   mn           = (data.m)*(data.n);
68*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetInt(NULL,NULL,"-time",&time_steps,NULL));
69c4762a1bSJed Brown 
70c4762a1bSJed Brown   /* set initial conditions */
71*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreate(PETSC_COMM_WORLD,&global));
72*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetSizes(global,PETSC_DECIDE,mn));
73*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetFromOptions(global));
74*5f80ce2aSJacob Faibussowitsch   CHKERRQ(Initial(global,&data));
75*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDuplicate(global,&x));
76c4762a1bSJed Brown 
77c4762a1bSJed Brown   /* create timestep context */
78*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSCreate(PETSC_COMM_WORLD,&ts));
79*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSMonitorSet(ts,Monitor,&data,NULL));
80*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetType(ts,TSEULER));
81c4762a1bSJed Brown   dt   = 0.1;
82c4762a1bSJed Brown   ftime_original = data.tfinal = 1.0;
83c4762a1bSJed Brown 
84*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetTimeStep(ts,dt));
85*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetMaxSteps(ts,time_steps));
86*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetMaxTime(ts,ftime_original));
87*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetExactFinalTime(ts,TS_EXACTFINALTIME_STEPOVER));
88*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetSolution(ts,global));
89c4762a1bSJed Brown 
90c4762a1bSJed Brown   /* set user provided RHSFunction and RHSJacobian */
91*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetRHSFunction(ts,NULL,RHSFunction,&data));
92*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(PETSC_COMM_WORLD,&J));
93*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,mn,mn));
94*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetFromOptions(J));
95*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJSetPreallocation(J,5,NULL));
96*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMPIAIJSetPreallocation(J,5,NULL,5,NULL));
97c4762a1bSJed Brown 
98*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHasName(NULL,NULL,"-ts_fd",&flg));
99c4762a1bSJed Brown   if (!flg) {
100*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetRHSJacobian(ts,J,J,RHSJacobian,&data));
101c4762a1bSJed Brown   } else {
102*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSGetSNES(ts,&snes));
103*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsHasName(NULL,NULL,"-fd_color",&fd_jacobian_coloring));
104c4762a1bSJed Brown     if (fd_jacobian_coloring) { /* Use finite differences with coloring */
105c4762a1bSJed Brown       /* Get data structure of J */
106c4762a1bSJed Brown       PetscBool pc_diagonal;
107*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscOptionsHasName(NULL,NULL,"-pc_diagonal",&pc_diagonal));
108c4762a1bSJed Brown       if (pc_diagonal) { /* the preconditioner of J is a diagonal matrix */
109c4762a1bSJed Brown         PetscInt    rstart,rend,i;
110c4762a1bSJed Brown         PetscScalar zero=0.0;
111*5f80ce2aSJacob Faibussowitsch         CHKERRQ(MatGetOwnershipRange(J,&rstart,&rend));
112c4762a1bSJed Brown         for (i=rstart; i<rend; i++) {
113*5f80ce2aSJacob Faibussowitsch           CHKERRQ(MatSetValues(J,1,&i,1,&i,&zero,INSERT_VALUES));
114c4762a1bSJed Brown         }
115*5f80ce2aSJacob Faibussowitsch         CHKERRQ(MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY));
116*5f80ce2aSJacob Faibussowitsch         CHKERRQ(MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY));
117c4762a1bSJed Brown       } else {
118c4762a1bSJed Brown         /* Fill the structure using the expensive SNESComputeJacobianDefault. Temporarily set up the TS so we can call this function */
119*5f80ce2aSJacob Faibussowitsch         CHKERRQ(TSSetType(ts,TSBEULER));
120*5f80ce2aSJacob Faibussowitsch         CHKERRQ(TSSetUp(ts));
121*5f80ce2aSJacob Faibussowitsch         CHKERRQ(SNESComputeJacobianDefault(snes,x,J,J,ts));
122c4762a1bSJed Brown       }
123c4762a1bSJed Brown 
124c4762a1bSJed Brown       /* create coloring context */
125*5f80ce2aSJacob Faibussowitsch       CHKERRQ(MatColoringCreate(J,&mc));
126*5f80ce2aSJacob Faibussowitsch       CHKERRQ(MatColoringSetType(mc,MATCOLORINGSL));
127*5f80ce2aSJacob Faibussowitsch       CHKERRQ(MatColoringSetFromOptions(mc));
128*5f80ce2aSJacob Faibussowitsch       CHKERRQ(MatColoringApply(mc,&iscoloring));
129*5f80ce2aSJacob Faibussowitsch       CHKERRQ(MatColoringDestroy(&mc));
130*5f80ce2aSJacob Faibussowitsch       CHKERRQ(MatFDColoringCreate(J,iscoloring,&matfdcoloring));
131*5f80ce2aSJacob Faibussowitsch       CHKERRQ(MatFDColoringSetFunction(matfdcoloring,(PetscErrorCode (*)(void))SNESTSFormFunction,ts));
132*5f80ce2aSJacob Faibussowitsch       CHKERRQ(MatFDColoringSetFromOptions(matfdcoloring));
133*5f80ce2aSJacob Faibussowitsch       CHKERRQ(MatFDColoringSetUp(J,iscoloring,matfdcoloring));
134*5f80ce2aSJacob Faibussowitsch       CHKERRQ(SNESSetJacobian(snes,J,J,SNESComputeJacobianDefaultColor,matfdcoloring));
135*5f80ce2aSJacob Faibussowitsch       CHKERRQ(ISColoringDestroy(&iscoloring));
136c4762a1bSJed Brown     } else { /* Use finite differences (slow) */
137*5f80ce2aSJacob Faibussowitsch       CHKERRQ(SNESSetJacobian(snes,J,J,SNESComputeJacobianDefault,NULL));
138c4762a1bSJed Brown     }
139c4762a1bSJed Brown   }
140c4762a1bSJed Brown 
141c4762a1bSJed Brown   /* Pick up a Petsc preconditioner */
142c4762a1bSJed Brown   /* one can always set method or preconditioner during the run time */
143*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetSNES(ts,&snes));
144*5f80ce2aSJacob Faibussowitsch   CHKERRQ(SNESGetKSP(snes,&ksp));
145*5f80ce2aSJacob Faibussowitsch   CHKERRQ(KSPGetPC(ksp,&pc));
146*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PCSetType(pc,PCJACOBI));
147*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetExactFinalTime(ts,TS_EXACTFINALTIME_STEPOVER));
148c4762a1bSJed Brown 
149*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetFromOptions(ts));
150*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetUp(ts));
151c4762a1bSJed Brown 
152c4762a1bSJed Brown   /* Test TSSetPostStep() */
153*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHasName(NULL,NULL,"-test_PostStep",&flg));
154c4762a1bSJed Brown   if (flg) {
155*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetPostStep(ts,PostStep));
156c4762a1bSJed Brown   }
157c4762a1bSJed Brown 
158*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetInt(NULL,NULL,"-NOUT",&NOUT,NULL));
159c4762a1bSJed Brown   for (iout=1; iout<=NOUT; iout++) {
160*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetMaxSteps(ts,time_steps));
161*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetMaxTime(ts,iout*ftime_original/NOUT));
162*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSolve(ts,global));
163*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSGetSolveTime(ts,&ftime));
164*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetTime(ts,ftime));
165*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetTimeStep(ts,dt));
166c4762a1bSJed Brown   }
167c4762a1bSJed Brown   /* Interpolate solution at tfinal */
168*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetSolution(ts,&global));
169*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSInterpolate(ts,ftime_original,global));
170c4762a1bSJed Brown 
171*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHasName(NULL,NULL,"-matlab_view",&flg));
172c4762a1bSJed Brown   if (flg) { /* print solution into a MATLAB file */
173*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIOpen(PETSC_COMM_WORLD,"out.m",&viewfile));
174*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerPushFormat(viewfile,PETSC_VIEWER_ASCII_MATLAB));
175*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecView(global,viewfile));
176*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerPopFormat(viewfile));
177*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerDestroy(&viewfile));
178c4762a1bSJed Brown   }
179c4762a1bSJed Brown 
180c4762a1bSJed Brown   /* free the memories */
181*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSDestroy(&ts));
182*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&global));
183*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&x));
184*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&J));
185*5f80ce2aSJacob Faibussowitsch   if (fd_jacobian_coloring) CHKERRQ(MatFDColoringDestroy(&matfdcoloring));
186c4762a1bSJed Brown   ierr = PetscFinalize();
187c4762a1bSJed Brown   return ierr;
188c4762a1bSJed Brown }
189c4762a1bSJed Brown 
190c4762a1bSJed Brown /* -------------------------------------------------------------------*/
191c4762a1bSJed Brown /* the initial function */
192c4762a1bSJed Brown PetscReal f_ini(PetscReal x,PetscReal y)
193c4762a1bSJed Brown {
194c4762a1bSJed Brown   PetscReal f;
195c4762a1bSJed Brown 
196c4762a1bSJed Brown   f=PetscExpReal(-20.0*(PetscPowRealInt(x-0.5,2)+PetscPowRealInt(y-0.5,2)));
197c4762a1bSJed Brown   return f;
198c4762a1bSJed Brown }
199c4762a1bSJed Brown 
200c4762a1bSJed Brown PetscErrorCode Initial(Vec global,void *ctx)
201c4762a1bSJed Brown {
202c4762a1bSJed Brown   Data           *data = (Data*)ctx;
203c4762a1bSJed Brown   PetscInt       m,row,col;
204c4762a1bSJed Brown   PetscReal      x,y,dx,dy;
205c4762a1bSJed Brown   PetscScalar    *localptr;
206c4762a1bSJed Brown   PetscInt       i,mybase,myend,locsize;
207c4762a1bSJed Brown 
208c4762a1bSJed Brown   PetscFunctionBeginUser;
209c4762a1bSJed Brown   /* make the local  copies of parameters */
210c4762a1bSJed Brown   m  = data->m;
211c4762a1bSJed Brown   dx = data->dx;
212c4762a1bSJed Brown   dy = data->dy;
213c4762a1bSJed Brown 
214c4762a1bSJed Brown   /* determine starting point of each processor */
215*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetOwnershipRange(global,&mybase,&myend));
216*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLocalSize(global,&locsize));
217c4762a1bSJed Brown 
218c4762a1bSJed Brown   /* Initialize the array */
219*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayWrite(global,&localptr));
220c4762a1bSJed Brown 
221c4762a1bSJed Brown   for (i=0; i<locsize; i++) {
222c4762a1bSJed Brown     row         = 1+(mybase+i)-((mybase+i)/m)*m;
223c4762a1bSJed Brown     col         = (mybase+i)/m+1;
224c4762a1bSJed Brown     x           = dx*row;
225c4762a1bSJed Brown     y           = dy*col;
226c4762a1bSJed Brown     localptr[i] = f_ini(x,y);
227c4762a1bSJed Brown   }
228c4762a1bSJed Brown 
229*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayWrite(global,&localptr));
230c4762a1bSJed Brown   PetscFunctionReturn(0);
231c4762a1bSJed Brown }
232c4762a1bSJed Brown 
233c4762a1bSJed Brown PetscErrorCode Monitor(TS ts,PetscInt step,PetscReal time,Vec global,void *ctx)
234c4762a1bSJed Brown {
235c4762a1bSJed Brown   VecScatter        scatter;
236c4762a1bSJed Brown   IS                from,to;
237c4762a1bSJed Brown   PetscInt          i,n,*idx,nsteps,maxsteps;
238c4762a1bSJed Brown   Vec               tmp_vec;
239c4762a1bSJed Brown   const PetscScalar *tmp;
240c4762a1bSJed Brown 
241c4762a1bSJed Brown   PetscFunctionBeginUser;
242*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetStepNumber(ts,&nsteps));
243c4762a1bSJed Brown   /* display output at selected time steps */
244*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetMaxSteps(ts, &maxsteps));
245c4762a1bSJed Brown   if (nsteps % 10 != 0) PetscFunctionReturn(0);
246c4762a1bSJed Brown 
247c4762a1bSJed Brown   /* Get the size of the vector */
248*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetSize(global,&n));
249c4762a1bSJed Brown 
250c4762a1bSJed Brown   /* Set the index sets */
251*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(n,&idx));
252c4762a1bSJed Brown   for (i=0; i<n; i++) idx[i]=i;
253c4762a1bSJed Brown 
254c4762a1bSJed Brown   /* Create local sequential vectors */
255*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreateSeq(PETSC_COMM_SELF,n,&tmp_vec));
256c4762a1bSJed Brown 
257c4762a1bSJed Brown   /* Create scatter context */
258*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,n,idx,PETSC_COPY_VALUES,&from));
259*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,n,idx,PETSC_COPY_VALUES,&to));
260*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterCreate(global,from,tmp_vec,to,&scatter));
261*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(scatter,global,tmp_vec,INSERT_VALUES,SCATTER_FORWARD));
262*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(scatter,global,tmp_vec,INSERT_VALUES,SCATTER_FORWARD));
263c4762a1bSJed Brown 
264*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(tmp_vec,&tmp));
265*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"At t[%D] =%14.2e u= %14.2e at the center \n",nsteps,(double)time,(double)PetscRealPart(tmp[n/2])));
266*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(tmp_vec,&tmp));
267c4762a1bSJed Brown 
268*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(idx));
269*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&from));
270*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&to));
271*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterDestroy(&scatter));
272*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&tmp_vec));
273c4762a1bSJed Brown   PetscFunctionReturn(0);
274c4762a1bSJed Brown }
275c4762a1bSJed Brown 
276c4762a1bSJed Brown PetscErrorCode RHSJacobian(TS ts,PetscReal t,Vec x,Mat A,Mat BB,void *ptr)
277c4762a1bSJed Brown {
278c4762a1bSJed Brown   Data           *data = (Data*)ptr;
279c4762a1bSJed Brown   PetscScalar    v[5];
280c4762a1bSJed Brown   PetscInt       idx[5],i,j,row;
281c4762a1bSJed Brown   PetscInt       m,n,mn;
282c4762a1bSJed Brown   PetscReal      dx,dy,a,epsilon,xc,xl,xr,yl,yr;
283c4762a1bSJed Brown 
284c4762a1bSJed Brown   PetscFunctionBeginUser;
285c4762a1bSJed Brown   m       = data->m;
286c4762a1bSJed Brown   n       = data->n;
287c4762a1bSJed Brown   mn      = m*n;
288c4762a1bSJed Brown   dx      = data->dx;
289c4762a1bSJed Brown   dy      = data->dy;
290c4762a1bSJed Brown   a       = data->a;
291c4762a1bSJed Brown   epsilon = data->epsilon;
292c4762a1bSJed Brown 
293c4762a1bSJed Brown   xc = -2.0*epsilon*(1.0/(dx*dx)+1.0/(dy*dy));
294c4762a1bSJed Brown   xl = 0.5*a/dx+epsilon/(dx*dx);
295c4762a1bSJed Brown   xr = -0.5*a/dx+epsilon/(dx*dx);
296c4762a1bSJed Brown   yl = 0.5*a/dy+epsilon/(dy*dy);
297c4762a1bSJed Brown   yr = -0.5*a/dy+epsilon/(dy*dy);
298c4762a1bSJed Brown 
299c4762a1bSJed Brown   row    = 0;
300c4762a1bSJed Brown   v[0]   = xc;  v[1] = xr;  v[2] = yr;
301c4762a1bSJed Brown   idx[0] = 0; idx[1] = 2; idx[2] = m;
302*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetValues(A,1,&row,3,idx,v,INSERT_VALUES));
303c4762a1bSJed Brown 
304c4762a1bSJed Brown   row    = m-1;
305c4762a1bSJed Brown   v[0]   = 2.0*xl; v[1] = xc;    v[2] = yr;
306c4762a1bSJed Brown   idx[0] = m-2;  idx[1] = m-1; idx[2] = m-1+m;
307*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetValues(A,1,&row,3,idx,v,INSERT_VALUES));
308c4762a1bSJed Brown 
309c4762a1bSJed Brown   for (i=1; i<m-1; i++) {
310c4762a1bSJed Brown     row    = i;
311c4762a1bSJed Brown     v[0]   = xl;    v[1] = xc;  v[2] = xr;    v[3] = yr;
312c4762a1bSJed Brown     idx[0] = i-1; idx[1] = i; idx[2] = i+1; idx[3] = i+m;
313*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValues(A,1,&row,4,idx,v,INSERT_VALUES));
314c4762a1bSJed Brown   }
315c4762a1bSJed Brown 
316c4762a1bSJed Brown   for (j=1; j<n-1; j++) {
317c4762a1bSJed Brown     row    = j*m;
318c4762a1bSJed Brown     v[0]   = xc;    v[1] = xr;    v[2] = yl;      v[3] = yr;
319c4762a1bSJed Brown     idx[0] = j*m; idx[1] = j*m; idx[2] = j*m-m; idx[3] = j*m+m;
320*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValues(A,1,&row,4,idx,v,INSERT_VALUES));
321c4762a1bSJed Brown 
322c4762a1bSJed Brown     row    = j*m+m-1;
323c4762a1bSJed Brown     v[0]   = xc;        v[1] = 2.0*xl;      v[2] = yl;          v[3] = yr;
324c4762a1bSJed Brown     idx[0] = j*m+m-1; idx[1] = j*m+m-1-1; idx[2] = j*m+m-1-m; idx[3] = j*m+m-1+m;
325*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValues(A,1,&row,4,idx,v,INSERT_VALUES));
326c4762a1bSJed Brown 
327c4762a1bSJed Brown     for (i=1; i<m-1; i++) {
328c4762a1bSJed Brown       row    = j*m+i;
329c4762a1bSJed Brown       v[0]   = xc;      v[1] = xl;        v[2] = xr;        v[3] = yl; v[4]=yr;
330c4762a1bSJed Brown       idx[0] = j*m+i; idx[1] = j*m+i-1; idx[2] = j*m+i+1; idx[3] = j*m+i-m;
331c4762a1bSJed Brown       idx[4] = j*m+i+m;
332*5f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetValues(A,1,&row,5,idx,v,INSERT_VALUES));
333c4762a1bSJed Brown     }
334c4762a1bSJed Brown   }
335c4762a1bSJed Brown 
336c4762a1bSJed Brown   row    = mn-m;
337c4762a1bSJed Brown   v[0]   = xc;     v[1] = xr;       v[2] = 2.0*yl;
338c4762a1bSJed Brown   idx[0] = mn-m; idx[1] = mn-m+1; idx[2] = mn-m-m;
339*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetValues(A,1,&row,3,idx,v,INSERT_VALUES));
340c4762a1bSJed Brown 
341c4762a1bSJed Brown   row    = mn-1;
342c4762a1bSJed Brown   v[0]   = xc;     v[1] = 2.0*xl; v[2] = 2.0*yl;
343c4762a1bSJed Brown   idx[0] = mn-1; idx[1] = mn-2; idx[2] = mn-1-m;
344*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetValues(A,1,&i,3,idx,v,INSERT_VALUES));
345c4762a1bSJed Brown 
346c4762a1bSJed Brown   for (i=1; i<m-1; i++) {
347c4762a1bSJed Brown     row    = mn-m+i;
348c4762a1bSJed Brown     v[0]   = xl;         v[1] = xc;       v[2] = xr;         v[3] = 2.0*yl;
349c4762a1bSJed Brown     idx[0] = mn-m+i-1; idx[1] = mn-m+i; idx[2] = mn-m+i+1; idx[3] = mn-m+i-m;
350*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValues(A,1,&row,4,idx,v,INSERT_VALUES));
351c4762a1bSJed Brown   }
352c4762a1bSJed Brown 
353*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY));
354*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY));
355c4762a1bSJed Brown 
356c4762a1bSJed Brown   PetscFunctionReturn(0);
357c4762a1bSJed Brown }
358c4762a1bSJed Brown 
359c4762a1bSJed Brown /* globalout = -a*(u_x+u_y) + epsilon*(u_xx+u_yy) */
360c4762a1bSJed Brown PetscErrorCode RHSFunction(TS ts,PetscReal t,Vec globalin,Vec globalout,void *ctx)
361c4762a1bSJed Brown {
362c4762a1bSJed Brown   Data              *data = (Data*)ctx;
363c4762a1bSJed Brown   PetscInt          m,n,mn;
364c4762a1bSJed Brown   PetscReal         dx,dy;
365c4762a1bSJed Brown   PetscReal         xc,xl,xr,yl,yr;
366c4762a1bSJed Brown   PetscReal         a,epsilon;
367c4762a1bSJed Brown   PetscScalar       *outptr;
368c4762a1bSJed Brown   const PetscScalar *inptr;
369c4762a1bSJed Brown   PetscInt          i,j,len;
370c4762a1bSJed Brown   IS                from,to;
371c4762a1bSJed Brown   PetscInt          *idx;
372c4762a1bSJed Brown   VecScatter        scatter;
373c4762a1bSJed Brown   Vec               tmp_in,tmp_out;
374c4762a1bSJed Brown 
375c4762a1bSJed Brown   PetscFunctionBeginUser;
376c4762a1bSJed Brown   m       = data->m;
377c4762a1bSJed Brown   n       = data->n;
378c4762a1bSJed Brown   mn      = m*n;
379c4762a1bSJed Brown   dx      = data->dx;
380c4762a1bSJed Brown   dy      = data->dy;
381c4762a1bSJed Brown   a       = data->a;
382c4762a1bSJed Brown   epsilon = data->epsilon;
383c4762a1bSJed Brown 
384c4762a1bSJed Brown   xc = -2.0*epsilon*(1.0/(dx*dx)+1.0/(dy*dy));
385c4762a1bSJed Brown   xl = 0.5*a/dx+epsilon/(dx*dx);
386c4762a1bSJed Brown   xr = -0.5*a/dx+epsilon/(dx*dx);
387c4762a1bSJed Brown   yl = 0.5*a/dy+epsilon/(dy*dy);
388c4762a1bSJed Brown   yr = -0.5*a/dy+epsilon/(dy*dy);
389c4762a1bSJed Brown 
390c4762a1bSJed Brown   /* Get the length of parallel vector */
391*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetSize(globalin,&len));
392c4762a1bSJed Brown 
393c4762a1bSJed Brown   /* Set the index sets */
394*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(len,&idx));
395c4762a1bSJed Brown   for (i=0; i<len; i++) idx[i]=i;
396c4762a1bSJed Brown 
397c4762a1bSJed Brown   /* Create local sequential vectors */
398*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreateSeq(PETSC_COMM_SELF,len,&tmp_in));
399*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDuplicate(tmp_in,&tmp_out));
400c4762a1bSJed Brown 
401c4762a1bSJed Brown   /* Create scatter context */
402*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,len,idx,PETSC_COPY_VALUES,&from));
403*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,len,idx,PETSC_COPY_VALUES,&to));
404*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterCreate(globalin,from,tmp_in,to,&scatter));
405*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(scatter,globalin,tmp_in,INSERT_VALUES,SCATTER_FORWARD));
406*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(scatter,globalin,tmp_in,INSERT_VALUES,SCATTER_FORWARD));
407*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterDestroy(&scatter));
408c4762a1bSJed Brown 
409c4762a1bSJed Brown   /*Extract income array - include ghost points */
410*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(tmp_in,&inptr));
411c4762a1bSJed Brown 
412c4762a1bSJed Brown   /* Extract outcome array*/
413*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayWrite(tmp_out,&outptr));
414c4762a1bSJed Brown 
415c4762a1bSJed Brown   outptr[0]   = xc*inptr[0]+xr*inptr[1]+yr*inptr[m];
416c4762a1bSJed Brown   outptr[m-1] = 2.0*xl*inptr[m-2]+xc*inptr[m-1]+yr*inptr[m-1+m];
417c4762a1bSJed Brown   for (i=1; i<m-1; i++) {
418c4762a1bSJed Brown     outptr[i] = xc*inptr[i]+xl*inptr[i-1]+xr*inptr[i+1]+yr*inptr[i+m];
419c4762a1bSJed Brown   }
420c4762a1bSJed Brown 
421c4762a1bSJed Brown   for (j=1; j<n-1; j++) {
422c4762a1bSJed Brown     outptr[j*m] = xc*inptr[j*m]+xr*inptr[j*m+1]+ yl*inptr[j*m-m]+yr*inptr[j*m+m];
423c4762a1bSJed Brown     outptr[j*m+m-1] = xc*inptr[j*m+m-1]+2.0*xl*inptr[j*m+m-1-1]+ yl*inptr[j*m+m-1-m]+yr*inptr[j*m+m-1+m];
424c4762a1bSJed Brown     for (i=1; i<m-1; i++) {
425c4762a1bSJed Brown       outptr[j*m+i] = xc*inptr[j*m+i]+xl*inptr[j*m+i-1]+xr*inptr[j*m+i+1]+yl*inptr[j*m+i-m]+yr*inptr[j*m+i+m];
426c4762a1bSJed Brown     }
427c4762a1bSJed Brown   }
428c4762a1bSJed Brown 
429c4762a1bSJed Brown   outptr[mn-m] = xc*inptr[mn-m]+xr*inptr[mn-m+1]+2.0*yl*inptr[mn-m-m];
430c4762a1bSJed Brown   outptr[mn-1] = 2.0*xl*inptr[mn-2]+xc*inptr[mn-1]+2.0*yl*inptr[mn-1-m];
431c4762a1bSJed Brown   for (i=1; i<m-1; i++) {
432c4762a1bSJed Brown     outptr[mn-m+i] = xc*inptr[mn-m+i]+xl*inptr[mn-m+i-1]+xr*inptr[mn-m+i+1]+2*yl*inptr[mn-m+i-m];
433c4762a1bSJed Brown   }
434c4762a1bSJed Brown 
435*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(tmp_in,&inptr));
436*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayWrite(tmp_out,&outptr));
437c4762a1bSJed Brown 
438*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterCreate(tmp_out,from,globalout,to,&scatter));
439*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(scatter,tmp_out,globalout,INSERT_VALUES,SCATTER_FORWARD));
440*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(scatter,tmp_out,globalout,INSERT_VALUES,SCATTER_FORWARD));
441c4762a1bSJed Brown 
442c4762a1bSJed Brown   /* Destroy idx aand scatter */
443*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&tmp_in));
444*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&tmp_out));
445*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&from));
446*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&to));
447*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterDestroy(&scatter));
448c4762a1bSJed Brown 
449*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(idx));
450c4762a1bSJed Brown   PetscFunctionReturn(0);
451c4762a1bSJed Brown }
452c4762a1bSJed Brown 
453c4762a1bSJed Brown PetscErrorCode PostStep(TS ts)
454c4762a1bSJed Brown {
455c4762a1bSJed Brown   PetscReal      t;
456c4762a1bSJed Brown 
457c4762a1bSJed Brown   PetscFunctionBeginUser;
458*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetTime(ts,&t));
459*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPrintf(PETSC_COMM_SELF,"  PostStep, t: %g\n",(double)t));
460c4762a1bSJed Brown   PetscFunctionReturn(0);
461c4762a1bSJed Brown }
462c4762a1bSJed Brown 
463c4762a1bSJed Brown /*TEST
464c4762a1bSJed Brown 
465c4762a1bSJed Brown     test:
466c4762a1bSJed Brown       args: -ts_fd -ts_type beuler
467c4762a1bSJed Brown       output_file: output/ex4.out
468c4762a1bSJed Brown 
469c4762a1bSJed Brown     test:
470c4762a1bSJed Brown       suffix: 2
471c4762a1bSJed Brown       args: -ts_fd -ts_type beuler
472c4762a1bSJed Brown       nsize: 2
473c4762a1bSJed Brown       output_file: output/ex4.out
474c4762a1bSJed Brown 
475c4762a1bSJed Brown     test:
476c4762a1bSJed Brown       suffix: 3
477c4762a1bSJed Brown       args: -ts_fd -ts_type cn
478c4762a1bSJed Brown 
479c4762a1bSJed Brown     test:
480c4762a1bSJed Brown       suffix: 4
481c4762a1bSJed Brown       args: -ts_fd -ts_type cn
482c4762a1bSJed Brown       output_file: output/ex4_3.out
483c4762a1bSJed Brown       nsize: 2
484c4762a1bSJed Brown 
485c4762a1bSJed Brown     test:
486c4762a1bSJed Brown       suffix: 5
487c4762a1bSJed Brown       args: -ts_type beuler -ts_fd -fd_color -mat_coloring_type sl
488c4762a1bSJed Brown       output_file: output/ex4.out
489c4762a1bSJed Brown 
490c4762a1bSJed Brown     test:
491c4762a1bSJed Brown       suffix: 6
492c4762a1bSJed Brown       args: -ts_type beuler -ts_fd -fd_color -mat_coloring_type sl
493c4762a1bSJed Brown       output_file: output/ex4.out
494c4762a1bSJed Brown       nsize: 2
495c4762a1bSJed Brown 
496c4762a1bSJed Brown     test:
497c4762a1bSJed Brown       suffix: 7
498c4762a1bSJed Brown       requires: !single
499c4762a1bSJed Brown       args: -ts_fd -ts_type beuler -test_PostStep -ts_dt .1
500c4762a1bSJed Brown 
501c4762a1bSJed Brown     test:
502c4762a1bSJed Brown       suffix: 8
503c4762a1bSJed Brown       requires: !single
504c4762a1bSJed Brown       args: -ts_type rk -ts_rk_type 5dp -ts_dt .01 -ts_adapt_type none -ts_view
505c4762a1bSJed Brown 
506c4762a1bSJed Brown TEST*/
507