Actual source code: ex17.c
petsc-3.4.0 2013-05-13
1: static const char help[] = "Time-dependent PDE in 1d. Simplified from ex15.c for illustrating how to solve DAEs. \n";
2: /*
3: u_t = uxx
4: 0 < x < 1;
5: At t=0: u(x) = exp(c*r*r*r), if r=PetscSqrtReal((x-.5)*(x-.5)) < .125
6: u(x) = 0.0 if r >= .125
9: Boundary conditions:
10: Dirichlet BC:
11: At x=0, x=1, u = 0.0
13: Neumann BC:
14: At x=0, x=1: du(x,t)/dx = 0
16: mpiexec -n 2 ./ex17 -da_grid_x 40 -ts_max_steps 2 -snes_monitor -ksp_monitor
17: ./ex17 -da_grid_x 40 -monitor_solution
18: ./ex17 -da_grid_x 100 -ts_type theta -ts_theta_theta 0.5 # Midpoint is not L-stable
19: ./ex17 -jac_type fd_coloring -da_grid_x 500 -boundary 1
20: ./ex17 -da_grid_x 100 -ts_type gl -ts_adapt_type none -ts_max_steps 2
21: */
23: #include <petscdmda.h>
24: #include <petscts.h>
26: typedef enum {JACOBIAN_ANALYTIC,JACOBIAN_FD_COLORING,JACOBIAN_FD_FULL} JacobianType;
27: static const char *const JacobianTypes[] = {"analytic","fd_coloring","fd_full","JacobianType","fd_",0};
29: /*
30: User-defined data structures and routines
31: */
32: typedef struct {
33: PetscReal c;
34: PetscInt boundary; /* Type of boundary condition */
35: PetscBool viewJacobian;
36: } AppCtx;
38: static PetscErrorCode FormIFunction(TS,PetscReal,Vec,Vec,Vec,void*);
39: static PetscErrorCode FormIJacobian(TS,PetscReal,Vec,Vec,PetscReal,Mat*,Mat*,MatStructure*,void*);
40: static PetscErrorCode FormInitialSolution(TS,Vec,void*);
44: int main(int argc,char **argv)
45: {
46: TS ts; /* nonlinear solver */
47: Vec u; /* solution, residual vectors */
48: Mat J; /* Jacobian matrix */
49: PetscInt maxsteps = 1000; /* iterations for convergence */
50: PetscInt nsteps;
51: PetscReal vmin,vmax,norm;
53: DM da;
54: PetscReal ftime,dt;
55: AppCtx user; /* user-defined work context */
56: JacobianType jacType;
58: PetscInitialize(&argc,&argv,(char*)0,help);
60: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
61: Create distributed array (DMDA) to manage parallel grid and vectors
62: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
63: DMDACreate1d(PETSC_COMM_WORLD,DMDA_BOUNDARY_NONE,-11,1,1,NULL,&da);
65: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
66: Extract global vectors from DMDA;
67: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
68: DMCreateGlobalVector(da,&u);
70: /* Initialize user application context */
71: user.c = -30.0;
72: user.boundary = 0; /* 0: Dirichlet BC; 1: Neumann BC */
73: user.viewJacobian = PETSC_FALSE;
75: PetscOptionsGetInt(NULL,"-boundary",&user.boundary,NULL);
76: PetscOptionsHasName(NULL,"-viewJacobian",&user.viewJacobian);
78: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
79: Create timestepping solver context
80: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
81: TSCreate(PETSC_COMM_WORLD,&ts);
82: TSSetProblemType(ts,TS_NONLINEAR);
83: TSSetType(ts,TSTHETA);
84: TSThetaSetTheta(ts,1.0); /* Make the Theta method behave like backward Euler */
85: TSSetIFunction(ts,NULL,FormIFunction,&user);
87: DMCreateMatrix(da,MATAIJ,&J);
88: jacType = JACOBIAN_ANALYTIC; /* use user-provide Jacobian */
89: TSSetIJacobian(ts,J,J,FormIJacobian,&user);
91: TSSetDM(ts,da); /* Use TSGetDM() to access. Setting here allows easy use of geometric multigrid. */
93: ftime = 1.0;
94: TSSetDuration(ts,maxsteps,ftime);
96: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
97: Set initial conditions
98: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
99: FormInitialSolution(ts,u,&user);
100: TSSetSolution(ts,u);
101: dt = .01;
102: TSSetInitialTimeStep(ts,0.0,dt);
104: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
105: Set runtime options
106: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
107: TSSetFromOptions(ts);
109: /* Use slow fd Jacobian or fast fd Jacobian with colorings.
110: Note: this requirs snes which is not created until TSSetUp()/TSSetFromOptions() is called */
111: PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"Options for Jacobian evaluation",NULL);
112: PetscOptionsEnum("-jac_type","Type of Jacobian","",JacobianTypes,(PetscEnum)jacType,(PetscEnum*)&jacType,0);
113: PetscOptionsEnd();
114: if (jacType == JACOBIAN_FD_COLORING) {
115: SNES snes;
116: TSGetSNES(ts,&snes);
117: SNESSetJacobian(snes,J,J,SNESComputeJacobianDefaultColor,0);
118: } else if (jacType == JACOBIAN_FD_FULL) {
119: SNES snes;
120: TSGetSNES(ts,&snes);
121: SNESSetJacobian(snes,J,J,SNESComputeJacobianDefault,&user);
122: }
124: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
125: Integrate ODE system
126: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
127: TSSolve(ts,u);
129: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
130: Compute diagnostics of the solution
131: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
132: VecNorm(u,NORM_1,&norm);
133: VecMax(u,NULL,&vmax);
134: VecMin(u,NULL,&vmin);
135: TSGetTimeStepNumber(ts,&nsteps);
136: TSGetTime(ts,&ftime);
137: PetscPrintf(PETSC_COMM_WORLD,"timestep %D: time %G, solution norm %G, max %G, min %G\n",nsteps,ftime,norm,vmax,vmin);
139: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
140: Free work space.
141: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
142: MatDestroy(&J);
143: VecDestroy(&u);
144: TSDestroy(&ts);
145: DMDestroy(&da);
147: PetscFinalize();
148: return(0);
149: }
150: /* ------------------------------------------------------------------- */
153: static PetscErrorCode FormIFunction(TS ts,PetscReal ftime,Vec U,Vec Udot,Vec F,void *ptr)
154: {
155: AppCtx *user=(AppCtx*)ptr;
156: DM da;
158: PetscInt i,Mx,xs,xm;
159: PetscReal hx,sx;
160: PetscScalar *u,*udot,*f;
161: Vec localU;
164: TSGetDM(ts,&da);
165: DMGetLocalVector(da,&localU);
166: DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,
167: PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);
169: hx = 1.0/(PetscReal)(Mx-1); sx = 1.0/(hx*hx);
171: /*
172: Scatter ghost points to local vector,using the 2-step process
173: DMGlobalToLocalBegin(),DMGlobalToLocalEnd().
174: By placing code between these two statements, computations can be
175: done while messages are in transition.
176: */
177: DMGlobalToLocalBegin(da,U,INSERT_VALUES,localU);
178: DMGlobalToLocalEnd(da,U,INSERT_VALUES,localU);
180: /* Get pointers to vector data */
181: DMDAVecGetArray(da,localU,&u);
182: DMDAVecGetArray(da,Udot,&udot);
183: DMDAVecGetArray(da,F,&f);
185: /* Get local grid boundaries */
186: DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);
188: /* Compute function over the locally owned part of the grid */
189: for (i=xs; i<xs+xm; i++) {
190: if (user->boundary == 0) { /* Dirichlet BC */
191: if (i == 0 || i == Mx-1) f[i] = u[i]; /* F = U */
192: else f[i] = udot[i] + (2.*u[i] - u[i-1] - u[i+1])*sx;
193: } else { /* Neumann BC */
194: if (i == 0) f[i] = u[0] - u[1];
195: else if (i == Mx-1) f[i] = u[i] - u[i-1];
196: else f[i] = udot[i] + (2.*u[i] - u[i-1] - u[i+1])*sx;
197: }
198: }
200: /* Restore vectors */
201: DMDAVecRestoreArray(da,localU,&u);
202: DMDAVecRestoreArray(da,Udot,&udot);
203: DMDAVecRestoreArray(da,F,&f);
204: DMRestoreLocalVector(da,&localU);
205: return(0);
206: }
208: /* --------------------------------------------------------------------- */
209: /*
210: IJacobian - Compute IJacobian = dF/dU + a dF/dUdot
211: */
214: PetscErrorCode FormIJacobian(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal a,Mat *J,Mat *Jpre,MatStructure *str,void *ctx)
215: {
217: PetscInt i,rstart,rend,Mx;
218: PetscReal hx,sx;
219: AppCtx *user = (AppCtx*)ctx;
220: DM da;
221: MatStencil col[3],row;
222: PetscInt nc;
223: PetscScalar vals[3];
226: TSGetDM(ts,&da);
227: MatGetOwnershipRange(*Jpre,&rstart,&rend);
228: DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,
229: PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);
230: hx = 1.0/(PetscReal)(Mx-1); sx = 1.0/(hx*hx);
231: for (i=rstart; i<rend; i++) {
232: nc = 0;
233: row.i = i;
234: if (user->boundary == 0 && (i == 0 || i == Mx-1)) {
235: col[nc].i = i; vals[nc++] = 1.0;
236: } else if (user->boundary > 0 && i == 0) { /* Left Neumann */
237: col[nc].i = i; vals[nc++] = 1.0;
238: col[nc].i = i+1; vals[nc++] = -1.0;
239: } else if (user->boundary > 0 && i == Mx-1) { /* Right Neumann */
240: col[nc].i = i-1; vals[nc++] = -1.0;
241: col[nc].i = i; vals[nc++] = 1.0;
242: } else { /* Interior */
243: col[nc].i = i-1; vals[nc++] = -1.0*sx;
244: col[nc].i = i; vals[nc++] = 2.0*sx + a;
245: col[nc].i = i+1; vals[nc++] = -1.0*sx;
246: }
247: MatSetValuesStencil(*Jpre,1,&row,nc,col,vals,INSERT_VALUES);
248: }
250: MatAssemblyBegin(*Jpre,MAT_FINAL_ASSEMBLY);
251: MatAssemblyEnd(*Jpre,MAT_FINAL_ASSEMBLY);
252: if (*J != *Jpre) {
253: MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
254: MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
255: }
256: if (user->viewJacobian) {
257: PetscPrintf(PETSC_COMM_WORLD,"Jpre:\n");
258: MatView(*Jpre,PETSC_VIEWER_STDOUT_WORLD);
259: }
260: return(0);
261: }
263: /* ------------------------------------------------------------------- */
266: PetscErrorCode FormInitialSolution(TS ts,Vec U,void *ptr)
267: {
268: AppCtx *user=(AppCtx*)ptr;
269: PetscReal c =user->c;
270: DM da;
272: PetscInt i,xs,xm,Mx;
273: PetscScalar *u;
274: PetscReal hx,x,r;
277: TSGetDM(ts,&da);
278: DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,
279: PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);
281: hx = 1.0/(PetscReal)(Mx-1);
283: /* Get pointers to vector data */
284: DMDAVecGetArray(da,U,&u);
286: /* Get local grid boundaries */
287: DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);
289: /* Compute function over the locally owned part of the grid */
290: for (i=xs; i<xs+xm; i++) {
291: x = i*hx;
292: r = PetscSqrtScalar((x-.5)*(x-.5));
293: if (r < .125) u[i] = PetscExpScalar(c*r*r*r);
294: else u[i] = 0.0;
295: }
297: /* Restore vectors */
298: DMDAVecRestoreArray(da,U,&u);
299: return(0);
300: }