Actual source code: ex16.c
petsc-3.14.6 2021-03-30
2: static char help[] = "Solves the van der Pol equation and demonstrate IMEX.\n\
3: Input parameters include:\n\
4: -mu : stiffness parameter\n\n";
6: /*
7: Concepts: TS^time-dependent nonlinear problems
8: Concepts: TS^van der Pol equation
9: Processors: 1
10: */
11: /* ------------------------------------------------------------------------
13: This program solves the van der Pol equation
14: y'' - \mu ((1-y^2)*y' - y) = 0 (1)
15: on the domain 0 <= x <= 1, with the boundary conditions
16: y(0) = 2, y'(0) = - 2/3 +10/(81*\mu) - 292/(2187*\mu^2),
17: This is a nonlinear equation. The well prepared initial condition gives errors that are not dominated by the first few steps of the method when \mu is large.
19: Notes:
20: This code demonstrates the TS solver interface to two variants of
21: linear problems, u_t = f(u,t), namely turning (1) into a system of
22: first order differential equations,
24: [ y' ] = [ z ]
25: [ z' ] [ \mu ((1 - y^2) z - y) ]
27: which then we can write as a vector equation
29: [ u_1' ] = [ u_2 ] (2)
30: [ u_2' ] [ \mu (1 - u_1^2) u_2 - u_1 ]
32: which is now in the desired form of u_t = f(u,t). One way that we
33: can split f(u,t) in (2) is to split by component,
35: [ u_1' ] = [ u_2 ] + [ 0 ]
36: [ u_2' ] [ 0 ] [ \mu ((1 - u_1^2) u_2 - u_1) ]
38: where
40: [ G(u,t) ] = [ u_2 ]
41: [ 0 ]
43: and
45: [ F(u',u,t) ] = [ u_1' ] - [ 0 ]
46: [ u_2' ] [ \mu ((1 - u_1^2) u_2 - u_1) ]
48: Using the definition of the Jacobian of F (from the PETSc user manual),
49: in the equation F(u',u,t) = G(u,t),
51: dF dF
52: J(F) = a * -- - --
53: du' du
55: where d is the partial derivative. In this example,
57: dF [ 1 ; 0 ]
58: -- = [ ]
59: du' [ 0 ; 1 ]
61: dF [ 0 ; 0 ]
62: -- = [ ]
63: du [ -\mu (2*u_1*u_2 + 1); \mu (1 - u_1^2) ]
65: Hence,
67: [ a ; 0 ]
68: J(F) = [ ]
69: [ \mu (2*u_1*u_2 + 1); a - \mu (1 - u_1^2) ]
71: ------------------------------------------------------------------------- */
73: #include <petscts.h>
75: typedef struct _n_User *User;
76: struct _n_User {
77: PetscReal mu;
78: PetscBool imex;
79: PetscReal next_output;
80: };
82: /*
83: * User-defined routines
84: */
85: static PetscErrorCode RHSFunction(TS ts,PetscReal t,Vec X,Vec F,void *ctx)
86: {
87: PetscErrorCode ierr;
88: User user = (User)ctx;
89: PetscScalar *f;
90: const PetscScalar *x;
93: VecGetArrayRead(X,&x);
94: VecGetArray(F,&f);
95: f[0] = (user->imex ? x[1] : 0);
96: f[1] = 0.0;
97: VecRestoreArrayRead(X,&x);
98: VecRestoreArray(F,&f);
99: return(0);
100: }
102: static PetscErrorCode IFunction(TS ts,PetscReal t,Vec X,Vec Xdot,Vec F,void *ctx)
103: {
104: PetscErrorCode ierr;
105: User user = (User)ctx;
106: const PetscScalar *x,*xdot;
107: PetscScalar *f;
110: VecGetArrayRead(X,&x);
111: VecGetArrayRead(Xdot,&xdot);
112: VecGetArray(F,&f);
113: f[0] = xdot[0] + (user->imex ? 0 : x[1]);
114: f[1] = xdot[1] - user->mu*((1. - x[0]*x[0])*x[1] - x[0]);
115: VecRestoreArrayRead(X,&x);
116: VecRestoreArrayRead(Xdot,&xdot);
117: VecRestoreArray(F,&f);
118: return(0);
119: }
121: static PetscErrorCode IJacobian(TS ts,PetscReal t,Vec X,Vec Xdot,PetscReal a,Mat A,Mat B,void *ctx)
122: {
123: PetscErrorCode ierr;
124: User user = (User)ctx;
125: PetscReal mu = user->mu;
126: PetscInt rowcol[] = {0,1};
127: const PetscScalar *x;
128: PetscScalar J[2][2];
131: VecGetArrayRead(X,&x);
132: J[0][0] = a; J[0][1] = (user->imex ? 0 : 1.);
133: J[1][0] = mu*(2.*x[0]*x[1]+1.); J[1][1] = a - mu*(1. - x[0]*x[0]);
134: MatSetValues(B,2,rowcol,2,rowcol,&J[0][0],INSERT_VALUES);
135: VecRestoreArrayRead(X,&x);
137: MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
138: MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
139: if (A != B) {
140: MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
141: MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
142: }
143: return(0);
144: }
146: static PetscErrorCode RegisterMyARK2(void)
147: {
151: {
152: const PetscReal
153: A[3][3] = {{0,0,0},
154: {0.41421356237309504880,0,0},
155: {0.75,0.25,0}},
156: At[3][3] = {{0,0,0},
157: {0.12132034355964257320,0.29289321881345247560,0},
158: {0.20710678118654752440,0.50000000000000000000,0.29289321881345247560}},
159: *bembedt = NULL,*bembed = NULL;
160: TSARKIMEXRegister("myark2",2,3,&At[0][0],NULL,NULL,&A[0][0],NULL,NULL,bembedt,bembed,0,NULL,NULL);
161: }
162: return(0);
163: }
165: /* Monitor timesteps and use interpolation to output at integer multiples of 0.1 */
166: static PetscErrorCode Monitor(TS ts,PetscInt step,PetscReal t,Vec X,void *ctx)
167: {
168: PetscErrorCode ierr;
169: const PetscScalar *x;
170: PetscReal tfinal, dt;
171: User user = (User)ctx;
172: Vec interpolatedX;
175: TSGetTimeStep(ts,&dt);
176: TSGetMaxTime(ts,&tfinal);
178: while (user->next_output <= t && user->next_output <= tfinal) {
179: VecDuplicate(X,&interpolatedX);
180: TSInterpolate(ts,user->next_output,interpolatedX);
181: VecGetArrayRead(interpolatedX,&x);
182: 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]));
183: VecRestoreArrayRead(interpolatedX,&x);
184: VecDestroy(&interpolatedX);
186: user->next_output += 0.1;
187: }
188: return(0);
189: }
191: int main(int argc,char **argv)
192: {
193: TS ts; /* nonlinear solver */
194: Vec x; /* solution, residual vectors */
195: Mat A; /* Jacobian matrix */
196: PetscInt steps;
197: PetscReal ftime = 0.5;
198: PetscBool monitor = PETSC_FALSE;
199: PetscScalar *x_ptr;
200: PetscMPIInt size;
201: struct _n_User user;
204: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
205: Initialize program
206: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
207: PetscInitialize(&argc,&argv,NULL,help);if (ierr) return ierr;
208: MPI_Comm_size(PETSC_COMM_WORLD,&size);
209: if (size != 1) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_WRONG_MPI_SIZE,"This is a uniprocessor example only!");
211: RegisterMyARK2();
213: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
214: Set runtime options
215: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
216: user.mu = 1000.0;
217: user.imex = PETSC_TRUE;
218: user.next_output = 0.0;
220: PetscOptionsGetReal(NULL,NULL,"-mu",&user.mu,NULL);
221: PetscOptionsGetBool(NULL,NULL,"-imex",&user.imex,NULL);
222: PetscOptionsGetBool(NULL,NULL,"-monitor",&monitor,NULL);
224: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
225: Create necessary matrix and vectors, solve same ODE on every process
226: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
227: MatCreate(PETSC_COMM_WORLD,&A);
228: MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,2,2);
229: MatSetFromOptions(A);
230: MatSetUp(A);
231: MatCreateVecs(A,&x,NULL);
233: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
234: Create timestepping solver context
235: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
236: TSCreate(PETSC_COMM_WORLD,&ts);
237: TSSetType(ts,TSBEULER);
238: TSSetRHSFunction(ts,NULL,RHSFunction,&user);
239: TSSetIFunction(ts,NULL,IFunction,&user);
240: TSSetIJacobian(ts,A,A,IJacobian,&user);
241: TSSetMaxTime(ts,ftime);
242: TSSetExactFinalTime(ts,TS_EXACTFINALTIME_STEPOVER);
243: if (monitor) {
244: TSMonitorSet(ts,Monitor,&user,NULL);
245: }
247: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
248: Set initial conditions
249: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
250: VecGetArray(x,&x_ptr);
251: x_ptr[0] = 2.0;
252: x_ptr[1] = -2.0/3.0 + 10.0/(81.0*user.mu) - 292.0/(2187.0*user.mu*user.mu);
253: VecRestoreArray(x,&x_ptr);
254: TSSetTimeStep(ts,0.01);
256: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
257: Set runtime options
258: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
259: TSSetFromOptions(ts);
261: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
262: Solve nonlinear system
263: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
264: TSSolve(ts,x);
265: TSGetSolveTime(ts,&ftime);
266: TSGetStepNumber(ts,&steps);
267: PetscPrintf(PETSC_COMM_WORLD,"mu %g, steps %D, ftime %g\n",(double)user.mu,steps,(double)ftime);
268: VecView(x,PETSC_VIEWER_STDOUT_WORLD);
270: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
271: Free work space. All PETSc objects should be destroyed when they
272: are no longer needed.
273: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
274: MatDestroy(&A);
275: VecDestroy(&x);
276: TSDestroy(&ts);
278: PetscFinalize();
279: return ierr;
280: }
282: /*TEST
284: test:
285: args: -ts_type arkimex -ts_arkimex_type myark2 -ts_adapt_type none
286: requires: !single
288: TEST*/