Actual source code: ct_vdp_imex.c
petsc-3.6.4 2016-04-12
1: /*
2: * ex_vdp.c
3: *
4: * Created on: Jun 1, 2012
5: * Author: Hong Zhang
6: */
7: static char help[] = "Solves the van der Pol equation. \n Input parameters include:\n";
9: /*
10: * Processors:1
11: */
13: /*
14: * This program solves the van der Pol equation
15: * y' = z (1)
16: * z' = (((1-y^2)*z-y)/eps (2)
17: * on the domain 0<=x<=0.5, with the initial conditions
18: * y(0) = 2,
19: * z(0) = -2/3 + 10/81*eps - 292/2187*eps^2-1814/19683*eps^3
20: * IMEX schemes are applied to the splitted equation
21: * [y'] = [z] + [0 ]
22: * [z'] [0] [(((1-y^2)*z-y)/eps]
23: *
24: * F(x)= [z]
25: * [0]
26: *
27: * G(x)= [y'] - [0 ]
28: * [z'] [(((1-y^2)*z-y)/eps]
29: *
30: * JG(x) = G_x + a G_xdot
31: */
33: #include <petscdmda.h>
34: #include <petscts.h>
36: typedef struct _User *User;
37: struct _User {
38: PetscReal mu; /*stiffness control coefficient: epsilon*/
39: };
41: static PetscErrorCode RHSFunction(TS,PetscReal,Vec,Vec,void*);
42: static PetscErrorCode IFunction(TS,PetscReal,Vec,Vec,Vec,void*);
43: static PetscErrorCode IJacobian(TS,PetscReal,Vec,Vec,PetscReal,Mat,Mat,void*);
48: int main(int argc, char **argv)
49: {
50: TS ts;
51: Vec x; /*solution vector*/
52: Mat A; /*Jacobian*/
53: PetscInt steps,maxsteps,mx,eimex_rowcol[2],two;
54: PetscErrorCode ierr;
55: PetscScalar *x_ptr;
56: PetscReal ftime,dt,norm;
57: Vec ref;
58: struct _User user; /* user-defined work context */
59: PetscViewer viewer;
61: PetscInitialize(&argc,&argv,NULL,help);
63: /* Initialize user application context */
64: PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"van der Pol options","");
65: user.mu = 1e0;
66: PetscOptionsReal("-eps","Stiffness controller","",user.mu,&user.mu,NULL);
67: PetscOptionsEnd();
69: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
70: Set runtime options
71: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
72: /*
73: PetscOptionsGetBool(NULL,"-monitor",&monitor,NULL);
74: */
76: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
77: Create necessary matrix and vectors, solve same ODE on every process
78: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
79: MatCreate(PETSC_COMM_WORLD,&A);
80: MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,2,2);
81: MatSetFromOptions(A);
82: MatSetUp(A);
83: MatCreateVecs(A,&x,NULL);
85: MatCreateVecs(A,&ref,NULL);
86: VecGetArray(ref,&x_ptr);
87: /*
88: * [0,1], mu=10^-3
89: */
90: /*
91: x_ptr[0] = -1.8881254106283;
92: x_ptr[1] = 0.7359074233370;*/
94: /*
95: * [0,0.5],mu=10^-3
96: */
97: /*
98: x_ptr[0] = 1.596980778659137;
99: x_ptr[1] = -1.029103015879544;
100: */
101: /*
102: * [0,0.5],mu=1
103: */
104: x_ptr[0] = 1.619084329683235;
105: x_ptr[1] = -0.803530465176385;
107: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
108: Create timestepping solver context
109: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
110: TSCreate(PETSC_COMM_WORLD,&ts);
111: TSSetType(ts,TSEIMEX);
112: TSSetRHSFunction(ts,NULL,RHSFunction,&user);
113: TSSetIFunction(ts,NULL,IFunction,&user);
114: TSSetIJacobian(ts,A,A,IJacobian,&user);
116: ftime = 1.1;
117: dt = 0.00001;
118: maxsteps = 100000;
119: TSSetDuration(ts,maxsteps,ftime);
120: TSSetInitialTimeStep(ts,0.0,dt);
121: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
122: Set initial conditions
123: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
124: VecGetArray(x,&x_ptr);
125: x_ptr[0] = 2.;
126: x_ptr[1] = -2./3. + 10./81.*(user.mu) - 292./2187.* (user.mu) * (user.mu)
127: -1814./19683.*(user.mu)*(user.mu)*(user.mu);
128: TSSetSolution(ts,x);
129: VecGetSize(x,&mx);
131: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
132: Set runtime options
133: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
134: TSSetFromOptions(ts);
136: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
137: Solve nonlinear system
138: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
139: TSSolve(ts,x);
140: TSGetTime(ts,&ftime);
141: TSGetTimeStepNumber(ts,&steps);
143: VecAXPY(x,-1.0,ref);
144: VecNorm(x,NORM_2,&norm);
145: TSGetTimeStep(ts,&dt);
147: eimex_rowcol[0] = 0; eimex_rowcol[1] = 0; two = 2;
148: PetscOptionsGetIntArray(NULL,"-ts_eimex_row_col",eimex_rowcol,&two,NULL);
149: PetscPrintf(PETSC_COMM_WORLD,"order %11s %18s %37s\n","dt","norm","final solution components 0 and 1");
150: VecGetArray(x,&x_ptr);
151: PetscPrintf(PETSC_COMM_WORLD,"(%D,%D) %10.8f %18.15f %18.15f %18.15f\n",eimex_rowcol[0],eimex_rowcol[1],(double)dt,(double)norm,(double)PetscRealPart(x_ptr[0]),(double)PetscRealPart(x_ptr[1]));
152: VecRestoreArray(x,&x_ptr);
154: /* Write line in convergence log */
155: PetscViewerCreate(PETSC_COMM_WORLD,&viewer);
156: PetscViewerSetType(viewer,PETSCVIEWERASCII);
157: PetscViewerFileSetMode(viewer,FILE_MODE_APPEND);
158: PetscViewerFileSetName(viewer,"eimex_nonstiff_vdp.txt");
159: PetscViewerASCIIPrintf(viewer,"%D %D %10.8f %18.15f\n",eimex_rowcol[0],eimex_rowcol[1],(double)dt,(double)norm);
160: PetscViewerDestroy(&viewer);
162: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
163: Free work space.
164: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
165: MatDestroy(&A);
166: VecDestroy(&x);
167: VecDestroy(&ref);
168: TSDestroy(&ts);
169: PetscFinalize();
170: return(0);
171: }
176: static PetscErrorCode RHSFunction(TS ts,PetscReal t,Vec X,Vec F,void *ptr)
177: {
178: PetscErrorCode ierr;
179: PetscScalar *f;
180: const PetscScalar *x;
183: VecGetArrayRead(X,&x);
184: VecGetArray(F,&f);
185: f[0] = x[1];
186: f[1] = 0.0;
187: VecRestoreArrayRead(X,&x);
188: VecRestoreArray(F,&f);
189: return(0);
190: }
194: static PetscErrorCode IFunction(TS ts,PetscReal t,Vec X,Vec Xdot,Vec F,void *ptr)
195: {
196: User user = (User)ptr;
197: PetscScalar *f;
198: const PetscScalar *x,*xdot;
199: PetscErrorCode ierr;
200:
202: VecGetArrayRead(X,&x);
203: VecGetArrayRead(Xdot,&xdot);
204: VecGetArray(F,&f);
205: f[0] = xdot[0];
206: f[1] = xdot[1]-((1.-x[0]*x[0])*x[1]-x[0])/user->mu;
207: VecRestoreArrayRead(X,&x);
208: VecRestoreArrayRead(Xdot,&xdot);
209: VecRestoreArray(F,&f);
210: return(0);
211: }
215: static PetscErrorCode IJacobian(TS ts,PetscReal t,Vec X,Vec Xdot,PetscReal a,Mat A,Mat B,void *ptr)
216: {
217: PetscErrorCode ierr;
218: User user = (User)ptr;
219: PetscReal mu = user->mu;
220: PetscInt rowcol[] = {0,1};
221: PetscScalar J[2][2];
222: const PetscScalar *x;
225: VecGetArrayRead(X,&x);
226: J[0][0] = a;
227: J[0][1] = 0;
228: J[1][0] = (2.*x[0]*x[1]+1.)/mu;
229: J[1][1] = a - (1. - x[0]*x[0])/mu;
230: MatSetValues(B,2,rowcol,2,rowcol,&J[0][0],INSERT_VALUES);
231: VecRestoreArrayRead(X,&x);
233: MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
234: MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
235: if (A != B) {
236: MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
237: MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
238: }
239: return(0);
240: }