Actual source code: ex7.c
petsc-dev 2014-02-02
2: static char help[] = ".\n";
4: /*
6: u_t = u_xx + R(u)
8: Where u(t,x,i) for i=0, .... N-1 where i+1 represents the void size
10: ex9.c is the 2d version of this code
11: */
13: #include <petscdmda.h>
14: #include <petscts.h>
16: /*
17: User-defined data structures and routines
18: */
20: /* AppCtx */
21: typedef struct {
22: PetscInt N; /* number of dofs */
23: } AppCtx;
25: extern PetscErrorCode IFunction(TS,PetscReal,Vec,Vec,Vec,void*);
26: extern PetscErrorCode InitialConditions(DM,Vec);
27: extern PetscErrorCode IJacobian(TS,PetscReal,Vec,Vec,PetscReal,Mat*,Mat*,MatStructure*,void*);
32: int main(int argc,char **argv)
33: {
34: TS ts; /* nonlinear solver */
35: Vec U; /* solution, residual vectors */
36: Mat J; /* Jacobian matrix */
37: PetscInt maxsteps = 1000;
39: DM da;
40: AppCtx user;
41: PetscInt i;
42: char Name[16];
44: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
45: Initialize program
46: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
47: PetscInitialize(&argc,&argv,(char*)0,help);
48: user.N = 1;
49: PetscOptionsGetInt(NULL,"-N",&user.N,NULL);
51: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
52: Create distributed array (DMDA) to manage parallel grid and vectors
53: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
54: DMDACreate1d(PETSC_COMM_WORLD, DMDA_BOUNDARY_MIRROR,-8,user.N,1,NULL,&da);
56: for (i=0; i<user.N; i++) {
57: PetscSNPrintf(Name,16,"Void size %d",(int)(i+1));
58: DMDASetFieldName(da,i,Name);
59: }
61: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
62: Extract global vectors from DMDA; then duplicate for remaining
63: vectors that are the same types
64: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
65: DMCreateGlobalVector(da,&U);
66: DMSetMatType(da,MATAIJ);
67: DMCreateMatrix(da,&J);
69: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
70: Create timestepping solver context
71: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
72: TSCreate(PETSC_COMM_WORLD,&ts);
73: TSSetType(ts,TSARKIMEX);
74: TSSetDM(ts,da);
75: TSSetProblemType(ts,TS_NONLINEAR);
76: TSSetIFunction(ts,NULL,IFunction,&user);
77: TSSetIJacobian(ts,J,J,IJacobian,&user);
80: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
81: Set initial conditions
82: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
83: InitialConditions(da,U);
84: TSSetSolution(ts,U);
86: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
87: Set solver options
88: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
89: TSSetInitialTimeStep(ts,0.0,.001);
90: TSSetDuration(ts,maxsteps,1.0);
91: TSSetFromOptions(ts);
93: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
94: Solve nonlinear system
95: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
96: TSSolve(ts,U);
98: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
99: Free work space. All PETSc objects should be destroyed when they
100: are no longer needed.
101: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
102: VecDestroy(&U);
103: MatDestroy(&J);
104: TSDestroy(&ts);
105: DMDestroy(&da);
107: PetscFinalize();
108: return(0);
109: }
110: /* ------------------------------------------------------------------- */
113: /*
114: IFunction - Evaluates nonlinear function, F(U).
116: Input Parameters:
117: . ts - the TS context
118: . U - input vector
119: . ptr - optional user-defined context, as set by SNESSetFunction()
121: Output Parameter:
122: . F - function vector
123: */
124: PetscErrorCode IFunction(TS ts,PetscReal ftime,Vec U,Vec Udot,Vec F,void *ptr)
125: {
126: DM da;
128: PetscInt i,c,Mx,xs,xm,N;
129: PetscReal hx,sx,x;
130: PetscScalar uxx;
131: PetscScalar **u,**f,**udot;
132: Vec localU;
135: TSGetDM(ts,&da);
136: DMGetLocalVector(da,&localU);
137: DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,&N,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);
139: hx = 1.0/(PetscReal)(Mx-1); sx = 1.0/(hx*hx);
141: /*
142: Scatter ghost points to local vector,using the 2-step process
143: DMGlobalToLocalBegin(),DMGlobalToLocalEnd().
144: By placing code between these two statements, computations can be
145: done while messages are in transition.
146: */
147: DMGlobalToLocalBegin(da,U,INSERT_VALUES,localU);
148: DMGlobalToLocalEnd(da,U,INSERT_VALUES,localU);
150: /*
151: Get pointers to vector data
152: */
153: DMDAVecGetArrayDOF(da,localU,&u);
154: DMDAVecGetArrayDOF(da,Udot,&udot);
155: DMDAVecGetArrayDOF(da,F,&f);
157: /*
158: Get local grid boundaries
159: */
160: DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);
162: /*
163: Compute function over the locally owned part of the grid
164: */
165: for (i=xs; i<xs+xm; i++) {
166: x = i*hx;
168: /* diffusion term */
169: for (c=0; c<N; c++) {
170: uxx = (-2.0*u[i][c] + u[i-1][c] + u[i+1][c])*sx;
171: f[i][c] = udot[i][c] - uxx;
172: }
174: /* reaction terms */
176: for (c=0; c<N/3; c++) {
177: f[i][c] += 500*u[i][c]*u[i][c] + 500*u[i][c]*u[i][c+1];
178: f[i][c+1] += -500*u[i][c]*u[i][c] + 500*u[i][c]*u[i][c+1];
179: f[i][c+2] -= 500*u[i][c]*u[i][c+1];
180: }
183: /* forcing term */
185: f[i][0] -= 5*PetscExpScalar((1.0 - x)*(1.0 - x));
187: }
189: /*
190: Restore vectors
191: */
192: DMDAVecRestoreArrayDOF(da,localU,&u);
193: DMDAVecRestoreArrayDOF(da,Udot,&udot);
194: DMDAVecRestoreArrayDOF(da,F,&f);
195: DMRestoreLocalVector(da,&localU);
196: return(0);
197: }
201: PetscErrorCode IJacobian(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal a,Mat *J,Mat *Jpre,MatStructure *str,void *ctx)
202: {
204: PetscInt i,c,Mx,xs,xm,nc;
205: DM da;
206: MatStencil col[3],row;
207: PetscScalar vals[3],hx,sx;
208: AppCtx *user = (AppCtx*)ctx;
209: PetscInt N = user->N;
210: PetscScalar **u;
213: TSGetDM(ts,&da);
214: DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);
215: DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);
217: hx = 1.0/(PetscReal)(Mx-1); sx = 1.0/(hx*hx);
219: DMDAVecGetArrayDOF(da,U,&u);
221: MatZeroEntries(*Jpre);
222: for (i=xs; i<xs+xm; i++) {
223: for (c=0; c<N; c++) {
224: nc = 0;
225: row.c = c; row.i = i;
226: col[nc].c = c; col[nc].i = i-1; vals[nc++] = -sx;
227: col[nc].c = c; col[nc].i = i; vals[nc++] = 2.0*sx + a;
228: col[nc].c = c; col[nc].i = i+1; vals[nc++] = -sx;
229: MatSetValuesStencil(*Jpre,1,&row,nc,col,vals,ADD_VALUES);
230: }
232: for (c=0; c<N/3; c++) {
233: nc = 0;
234: row.c = c; row.i = i;
235: col[nc].c = c; col[nc].i = i; vals[nc++] = 1000*u[i][c] + 500*u[i][c+1];
236: col[nc].c = c+1; col[nc].i = i; vals[nc++] = 500*u[i][c];
237: MatSetValuesStencil(*Jpre,1,&row,nc,col,vals,ADD_VALUES);
239: nc = 0;
240: row.c = c+1; row.i = i;
241: col[nc].c = c; col[nc].i = i; vals[nc++] = -1000*u[i][c] + 500*u[i][c+1];
242: col[nc].c = c+1; col[nc].i = i; vals[nc++] = 500*u[i][c];
243: MatSetValuesStencil(*Jpre,1,&row,nc,col,vals,ADD_VALUES);
245: nc = 0;
246: row.c = c+2; row.i = i;
247: col[nc].c = c; col[nc].i = i; vals[nc++] = -500*u[i][c+1];
248: col[nc].c = c+1; col[nc].i = i; vals[nc++] = -500*u[i][c];
249: MatSetValuesStencil(*Jpre,1,&row,nc,col,vals,ADD_VALUES);
251: }
252: }
253: MatAssemblyBegin(*Jpre,MAT_FINAL_ASSEMBLY);
254: MatAssemblyEnd(*Jpre,MAT_FINAL_ASSEMBLY);
255: if (*J != *Jpre) {
256: MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);
257: MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);
258: }
259: DMDAVecRestoreArrayDOF(da,U,&u);
260: return(0);
261: }
263: /* ------------------------------------------------------------------- */
266: PetscErrorCode InitialConditions(DM da,Vec U)
267: {
269: PetscInt i,c,xs,xm,Mx,N;
270: PetscScalar **u;
271: PetscReal hx,x;
274: DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,&N,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);
276: hx = 1.0/(PetscReal)(Mx-1);
278: /*
279: Get pointers to vector data
280: */
281: DMDAVecGetArrayDOF(da,U,&u);
283: /*
284: Get local grid boundaries
285: */
286: DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);
288: /*
289: Compute function over the locally owned part of the grid
290: */
291: for (i=xs; i<xs+xm; i++) {
292: x = i*hx;
293: for (c=0; c<N; c++) u[i][c] = 0.0; /*PetscCosScalar(PETSC_PI*x);*/
294: }
296: /*
297: Restore vectors
298: */
299: DMDAVecRestoreArrayDOF(da,U,&u);
300: return(0);
301: }