Actual source code: ex16.c
petsc-3.3-p7 2013-05-11
2: /* Program usage: ./ex16 [-help] [all PETSc options] */
4: static char help[] = "Solves the van der Pol equation.\n\
5: Input parameters include:\n\
6: -mu : stiffness parameter\n\n";
8: /*
9: Concepts: TS^time-dependent nonlinear problems
10: Concepts: TS^van der Pol equation
11: Processors: 1
12: */
13: /* ------------------------------------------------------------------------
15: This program solves the van der Pol equation
16: y'' - \mu (1-y^2)*y' + y = 0 (1)
17: on the domain 0 <= x <= 1, with the boundary conditions
18: y(0) = 2, y'(0) = 0,
19: This is a nonlinear equation.
21: Notes:
22: This code demonstrates the TS solver interface to two variants of
23: linear problems, u_t = f(u,t), namely turning (1) into a system of
24: first order differential equations,
26: [ y' ] = [ z ]
27: [ z' ] [ \mu (1 - y^2) z - y ]
29: which then we can write as a vector equation
31: [ u_1' ] = [ u_2 ] (2)
32: [ u_2' ] [ \mu (1 - u_1^2) u_2 - u_1 ]
34: which is now in the desired form of u_t = f(u,t). One way that we
35: can split f(u,t) in (2) is to split by component,
37: [ u_1' ] = [ u_2 ] + [ 0 ]
38: [ u_2' ] [ 0 ] [ \mu (1 - u_1^2) u_2 - u_1 ]
40: where
42: [ F(u,t) ] = [ u_2 ]
43: [ 0 ]
45: and
47: [ G(u',u,t) ] = [ u_1' ] - [ 0 ]
48: [ u_2' ] [ \mu (1 - u_1^2) u_2 - u_1 ]
50: Using the definition of the Jacobian of G (from the PETSc user manual),
51: in the equation G(u',u,t) = F(u,t),
53: dG dG
54: J(G) = a * -- - --
55: du' du
57: where d is the partial derivative. In this example,
59: dG [ 1 ; 0 ]
60: -- = [ ]
61: du' [ 0 ; 1 ]
63: dG [ 0 ; 0 ]
64: -- = [ ]
65: du [ -2 \mu u_1 - 1; \mu (1 - u_1^2) ]
67: Hence,
69: [ a ; 0 ]
70: J(G) = [ ]
71: [ 2 \mu u_1 + 1; a - \mu (1 - u_1^2) ]
73: ------------------------------------------------------------------------- */
75: #include <petscts.h>
77: typedef struct _n_User *User;
78: struct _n_User {
79: PetscReal mu;
80: PetscBool imex;
81: PetscReal next_output;
82: };
84: /*
85: * User-defined routines
86: */
89: static PetscErrorCode RHSFunction(TS ts,PetscReal t,Vec X,Vec F,void *ctx)
90: {
92: User user = (User)ctx;
93: PetscScalar *x,*f;
96: VecGetArray(X,&x);
97: VecGetArray(F,&f);
98: f[0] = (user->imex ? x[1] : 0);
99: f[1] = 0.0;
100: VecRestoreArray(X,&x);
101: VecRestoreArray(F,&f);
102: return(0);
103: }
107: static PetscErrorCode IFunction(TS ts,PetscReal t,Vec X,Vec Xdot,Vec F,void *ctx)
108: {
110: User user = (User)ctx;
111: PetscScalar *x,*xdot,*f;
114: VecGetArray(X,&x);
115: VecGetArray(Xdot,&xdot);
116: VecGetArray(F,&f);
117: f[0] = xdot[0] + (user->imex ? 0 : x[1]);
118: f[1] = xdot[1] - user->mu*(1. - x[0]*x[0])*x[1] + x[0];
119: VecRestoreArray(X,&x);
120: VecRestoreArray(Xdot,&xdot);
121: VecRestoreArray(F,&f);
122: return(0);
123: }
127: static PetscErrorCode IJacobian(TS ts,PetscReal t,Vec X,Vec Xdot,PetscReal a,Mat *A,Mat *B,MatStructure *flag,void *ctx)
128: {
130: User user = (User)ctx;
131: PetscReal mu = user->mu;
132: PetscInt rowcol[] = {0,1};
133: PetscScalar *x,J[2][2];
136: VecGetArray(X,&x);
137: J[0][0] = a; J[0][1] = (user->imex ? 0 : 1.);
138: J[1][0] = 2.*mu*x[0]*x[1]+1.; J[1][1] = a - mu*(1. - x[0]*x[0]);
139: MatSetValues(*B,2,rowcol,2,rowcol,&J[0][0],INSERT_VALUES);
140: VecRestoreArray(X,&x);
142: MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);
143: MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);
144: if (*A != *B) {
145: MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);
146: MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);
147: }
148: *flag = SAME_NONZERO_PATTERN;
149: return(0);
150: }
154: static PetscErrorCode RegisterMyARK2(void)
155: {
159: {
160: const PetscReal
161: A[3][3] = {{0,0,0},
162: {0.41421356237309504880,0,0},
163: {0.75,0.25,0}},
164: At[3][3] = {{0,0,0},
165: {0.12132034355964257320,0.29289321881345247560,0},
166: {0.20710678118654752440,0.50000000000000000000,0.29289321881345247560}},
167: *bembedt = PETSC_NULL,*bembed = PETSC_NULL;
168: TSARKIMEXRegister("myark2",2,3,&At[0][0],PETSC_NULL,PETSC_NULL,&A[0][0],PETSC_NULL,PETSC_NULL,bembedt,bembed,0,PETSC_NULL,PETSC_NULL);
169: }
170: return(0);
171: }
175: /* Monitor timesteps and use interpolation to output at integer multiples of 0.1 */
176: static PetscErrorCode Monitor(TS ts,PetscInt step,PetscReal t,Vec X,void *ctx)
177: {
179: const PetscScalar *x;
180: PetscReal tfinal, dt;
181: User user = (User)ctx;
182: Vec interpolatedX;
185: TSGetTimeStep(ts,&dt);
186: TSGetDuration(ts,PETSC_NULL,&tfinal);
188: while (user->next_output <= t && user->next_output <= tfinal) {
189: VecDuplicate(X,&interpolatedX);
190: TSInterpolate(ts,user->next_output,interpolatedX);
191: VecGetArrayRead(interpolatedX,&x);
192: PetscPrintf(PETSC_COMM_WORLD,"[%.1f] %D TS %.6f (dt = %.6f) X % 12.6e % 12.6e\n",user->next_output,step,t,dt,(double)PetscRealPart(x[0]),(double)PetscRealPart(x[1]));
193: VecRestoreArrayRead(interpolatedX,&x);
194: VecDestroy(&interpolatedX);
195: user->next_output += 0.1;
196: }
197: return(0);
198: }
202: int main(int argc,char **argv)
203: {
204: TS ts; /* nonlinear solver */
205: Vec x; /* solution, residual vectors */
206: Mat A; /* Jacobian matrix */
207: PetscInt steps;
208: PetscReal ftime=0.5;
209: PetscBool monitor = PETSC_FALSE;
210: PetscScalar *x_ptr;
211: PetscMPIInt size;
212: struct _n_User user;
213: PetscErrorCode ierr;
215: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
216: Initialize program
217: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
218: PetscInitialize(&argc,&argv,PETSC_NULL,help);
220: MPI_Comm_size(PETSC_COMM_WORLD,&size);
221: if (size != 1) SETERRQ(PETSC_COMM_SELF,1,"This is a uniprocessor example only!");
223: RegisterMyARK2();
225: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
226: Set runtime options
227: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
228: user.mu = 1000;
229: user.imex = PETSC_TRUE;
230: user.next_output = 0.0;
231: PetscOptionsGetReal(PETSC_NULL,"-mu",&user.mu,PETSC_NULL);
232: PetscOptionsGetBool(PETSC_NULL,"-imex",&user.imex,PETSC_NULL);
233: PetscOptionsGetBool(PETSC_NULL,"-monitor",&monitor,PETSC_NULL);
235: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
236: Create necessary matrix and vectors, solve same ODE on every process
237: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
238: MatCreate(PETSC_COMM_WORLD,&A);
239: MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,2,2);
240: MatSetFromOptions(A);
242: MatGetVecs(A,&x,PETSC_NULL);
244: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
245: Create timestepping solver context
246: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
247: TSCreate(PETSC_COMM_WORLD,&ts);
248: TSSetType(ts,TSBEULER);
249: TSSetRHSFunction(ts,PETSC_NULL,RHSFunction,&user);
250: TSSetIFunction(ts,PETSC_NULL,IFunction,&user);
251: TSSetIJacobian(ts,A,A,IJacobian,&user);
252: TSSetDuration(ts,PETSC_DEFAULT,ftime);
253: if (monitor) {
254: TSMonitorSet(ts,Monitor,&user,PETSC_NULL);
255: }
257: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
258: Set initial conditions
259: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
260: VecGetArray(x,&x_ptr);
261: x_ptr[0] = 2; x_ptr[1] = 0.66666654321;
262: VecRestoreArray(x,&x_ptr);
263: TSSetInitialTimeStep(ts,0.0,.001);
265: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
266: Set runtime options
267: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
268: TSSetFromOptions(ts);
270: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
271: Solve nonlinear system
272: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
273: TSSolve(ts,x,&ftime);
274: TSGetTimeStepNumber(ts,&steps);
275: PetscPrintf(PETSC_COMM_WORLD,"mu %G, steps %D, ftime %G\n",user.mu,steps,ftime);
276: VecView(x,PETSC_VIEWER_STDOUT_WORLD);
278: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
279: Free work space. All PETSc objects should be destroyed when they
280: are no longer needed.
281: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
282: MatDestroy(&A);
283: VecDestroy(&x);
284: TSDestroy(&ts);
286: PetscFinalize();
287: return(0);
288: }