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