Actual source code: ex7.c
petsc-3.7.4 2016-10-02
2: static char help[] = "Time-dependent PDE in 2d for calculating joint PDF. \n";
3: /*
4: p_t = -x_t*p_x -y_t*p_y + f(t)*p_yy
5: xmin < x < xmax, ymin < y < ymax;
7: Boundary conditions Neumman using mirror values
9: Note that x_t and y_t in the above are given functions of x and y; they are not derivatives of x and y.
10: x_t = (y - ws) y_t = (ws/2H)*(Pm - Pmax*sin(x))
12: */
14: #include <petscdm.h>
15: #include <petscdmda.h>
16: #include <petscts.h>
18: /*
19: User-defined data structures and routines
20: */
21: typedef struct {
22: PetscScalar ws; /* Synchronous speed */
23: PetscScalar H; /* Inertia constant */
24: PetscScalar D; /* Damping constant */
25: PetscScalar Pmax; /* Maximum power output of generator */
26: PetscScalar PM_min; /* Mean mechanical power input */
27: PetscScalar lambda; /* correlation time */
28: PetscScalar q; /* noise strength */
29: PetscScalar mux; /* Initial average angle */
30: PetscScalar sigmax; /* Standard deviation of initial angle */
31: PetscScalar muy; /* Average speed */
32: PetscScalar sigmay; /* standard deviation of initial speed */
33: PetscScalar rho; /* Cross-correlation coefficient */
34: PetscScalar xmin; /* left boundary of angle */
35: PetscScalar xmax; /* right boundary of angle */
36: PetscScalar ymin; /* bottom boundary of speed */
37: PetscScalar ymax; /* top boundary of speed */
38: PetscScalar dx; /* x step size */
39: PetscScalar dy; /* y step size */
40: PetscScalar disper_coe; /* Dispersion coefficient */
41: DM da;
42: PetscInt st_width; /* Stencil width */
43: DMBoundaryType bx; /* x boundary type */
44: DMBoundaryType by; /* y boundary type */
45: PetscBool nonoiseinitial;
46: } AppCtx;
48: PetscErrorCode Parameter_settings(AppCtx*);
49: PetscErrorCode ini_bou(Vec,AppCtx*);
50: PetscErrorCode IFunction(TS,PetscReal,Vec,Vec,Vec,void*);
51: PetscErrorCode IJacobian(TS,PetscReal,Vec,Vec,PetscReal,Mat,Mat,void*);
52: PetscErrorCode PostStep(TS);
56: int main(int argc, char **argv)
57: {
59: Vec x; /* Solution vector */
60: TS ts; /* Time-stepping context */
61: AppCtx user; /* Application context */
62: PetscViewer viewer;
64: PetscInitialize(&argc,&argv,"petscopt_ex7", help);
66: /* Get physics and time parameters */
67: Parameter_settings(&user);
68: /* Create a 2D DA with dof = 1 */
69: DMDACreate2d(PETSC_COMM_WORLD,user.bx,user.by,DMDA_STENCIL_STAR,-4,-4,PETSC_DECIDE,PETSC_DECIDE,1,user.st_width,NULL,NULL,&user.da);
70: /* Set x and y coordinates */
71: DMDASetUniformCoordinates(user.da,user.xmin,user.xmax,user.ymin,user.ymax,0,0);
72: DMDASetCoordinateName(user.da,0,"X - the angle");
73: DMDASetCoordinateName(user.da,1,"Y - the speed");
75: /* Get global vector x from DM */
76: DMCreateGlobalVector(user.da,&x);
78: ini_bou(x,&user);
79: PetscViewerBinaryOpen(PETSC_COMM_WORLD,"ini_x",FILE_MODE_WRITE,&viewer);
80: VecView(x,viewer);
81: PetscViewerDestroy(&viewer);
83: TSCreate(PETSC_COMM_WORLD,&ts);
84: TSSetDM(ts,user.da);
85: TSSetProblemType(ts,TS_NONLINEAR);
86: TSSetType(ts,TSARKIMEX);
87: TSSetIFunction(ts,NULL,IFunction,&user);
88: /* TSSetIJacobian(ts,NULL,NULL,IJacobian,&user); */
89: TSSetApplicationContext(ts,&user);
90: TSSetInitialTimeStep(ts,0.0,.005);
91: TSSetFromOptions(ts);
92: TSSetPostStep(ts,PostStep);
93: TSSolve(ts,x);
95: PetscViewerBinaryOpen(PETSC_COMM_WORLD,"fin_x",FILE_MODE_WRITE,&viewer);
96: VecView(x,viewer);
97: PetscViewerDestroy(&viewer);
99: VecDestroy(&x);
100: DMDestroy(&user.da);
101: TSDestroy(&ts);
102: PetscFinalize();
103: return 0;
104: }
108: PetscErrorCode PostStep(TS ts)
109: {
111: Vec X,gc;
112: AppCtx *user;
113: PetscScalar sum = 0,asum;
114: PetscReal t,**p;
115: DMDACoor2d **coors;
116: DM cda;
117: PetscInt i,j,xs,ys,xm,ym;
120: TSGetApplicationContext(ts,&user);
121: TSGetTime(ts,&t);
122: TSGetSolution(ts,&X);
124: DMGetCoordinateDM(user->da,&cda);
125: DMDAGetCorners(cda,&xs,&ys,0,&xm,&ym,0);
126: DMGetCoordinates(user->da,&gc);
127: DMDAVecGetArrayRead(cda,gc,&coors);
128: DMDAVecGetArrayRead(user->da,X,&p);
129: for (i=xs; i < xs+xm; i++) {
130: for (j=ys; j < ys+ym; j++) {
131: if (coors[j][i].y < 5) sum += p[j][i];
132: }
133: }
134: DMDAVecRestoreArrayRead(cda,gc,&coors);
135: DMDAVecRestoreArrayRead(user->da,X,&p);
136: MPI_Allreduce(&sum,&asum,1,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)ts));
137: PetscPrintf(PETSC_COMM_WORLD,"sum(p)*dw*dtheta at t = %f = %f\n",(double)t,(double)(asum));
138: if (sum < 1.0e-2) {
139: TSSetConvergedReason(ts,TS_CONVERGED_USER);
140: PetscPrintf(PETSC_COMM_WORLD,"Exiting TS as the integral of PDF is almost zero\n");
141: }
142: return(0);
143: }
147: PetscErrorCode ini_bou(Vec X,AppCtx* user)
148: {
150: DM cda;
151: DMDACoor2d **coors;
152: PetscScalar **p;
153: Vec gc;
154: PetscInt i,j;
155: PetscInt xs,ys,xm,ym,M,N;
156: PetscScalar xi,yi;
157: PetscScalar sigmax=user->sigmax,sigmay=user->sigmay;
158: PetscScalar rho =user->rho;
159: PetscScalar mux =user->mux,muy=user->muy;
160: PetscMPIInt rank;
161: PetscScalar sum;
164: MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
165: DMDAGetInfo(user->da,NULL,&M,&N,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
166: user->dx = (user->xmax - user->xmin)/(M-1); user->dy = (user->ymax - user->ymin)/(N-1);
167: DMGetCoordinateDM(user->da,&cda);
168: DMGetCoordinates(user->da,&gc);
169: DMDAVecGetArray(cda,gc,&coors);
170: DMDAVecGetArray(user->da,X,&p);
171: DMDAGetCorners(cda,&xs,&ys,0,&xm,&ym,0);
173: /* mux and muy need to be grid points in the x and y-direction otherwise the solution goes unstable
174: muy is set by choosing the y domain, no. of grid points along y-direction so that muy is a grid point
175: in the y-direction. We only modify mux here
176: */
177: mux = user->mux = coors[0][M/2+10].x; /* For -pi < x < pi, this should be some angle between 0 and pi/2 */
178: if (user->nonoiseinitial) {
179: for (i=xs; i < xs+xm; i++) {
180: for (j=ys; j < ys+ym; j++) {
181: xi = coors[j][i].x; yi = coors[j][i].y;
182: if ((xi == mux) && (yi == muy)) {
183: p[j][i] = 1.0;
184: }
185: }
186: }
187: } else {
188: /* Change PM_min accordingly */
189: user->PM_min = user->Pmax*PetscSinScalar(mux);
190: for (i=xs; i < xs+xm; i++) {
191: for (j=ys; j < ys+ym; j++) {
192: xi = coors[j][i].x; yi = coors[j][i].y;
193: p[j][i] = (0.5/(PETSC_PI*sigmax*sigmay*PetscSqrtScalar(1.0-rho*rho)))*PetscExpScalar(-0.5/(1-rho*rho)*(PetscPowScalar((xi-mux)/sigmax,2) + PetscPowScalar((yi-muy)/sigmay,2) - 2*rho*(xi-mux)*(yi-muy)/(sigmax*sigmay)));
194: }
195: }
196: }
197: DMDAVecRestoreArray(cda,gc,&coors);
198: DMDAVecRestoreArray(user->da,X,&p);
199: VecSum(X,&sum);
200: VecScale(X,1.0/sum);
201: return(0);
202: }
204: /* First advection term */
207: PetscErrorCode adv1(PetscScalar **p,PetscScalar y,PetscInt i,PetscInt j,PetscInt M,PetscScalar *p1,AppCtx *user)
208: {
209: PetscScalar f,fpos,fneg;
211: f = (y - user->ws);
212: fpos = PetscMax(f,0);
213: fneg = PetscMin(f,0);
214: if (user->st_width == 1) {
215: *p1 = fpos*(p[j][i] - p[j][i-1])/user->dx + fneg*(p[j][i+1] - p[j][i])/user->dx;
216: } else if (user->st_width == 2) {
217: *p1 = fpos*(3*p[j][i] - 4*p[j][i-1] + p[j][i-2])/(2*user->dx) + fneg*(-p[j][i+2] + 4*p[j][i+1] - 3*p[j][i])/(2*user->dx);
218: } else if (user->st_width == 3) {
219: *p1 = fpos*(2*p[j][i+1] + 3*p[j][i] - 6*p[j][i-1] + p[j][i-2])/(6*user->dx) + fneg*(-p[j][i+2] + 6*p[j][i+1] - 3*p[j][i] - 2*p[j][i-1])/(6*user->dx);
220: }
221: /* *p1 = f*(p[j][i+1] - p[j][i-1])/user->dx;*/
222: return(0);
223: }
225: /* Second advection term */
228: PetscErrorCode adv2(PetscScalar **p,PetscScalar x,PetscInt i,PetscInt j,PetscInt N,PetscScalar *p2,AppCtx *user)
229: {
230: PetscScalar f,fpos,fneg;
232: f = (user->ws/(2*user->H))*(user->PM_min - user->Pmax*PetscSinScalar(x));
233: fpos = PetscMax(f,0);
234: fneg = PetscMin(f,0);
235: if (user->st_width == 1) {
236: *p2 = fpos*(p[j][i] - p[j-1][i])/user->dy + fneg*(p[j+1][i] - p[j][i])/user->dy;
237: } else if (user->st_width ==2) {
238: *p2 = fpos*(3*p[j][i] - 4*p[j-1][i] + p[j-2][i])/(2*user->dy) + fneg*(-p[j+2][i] + 4*p[j+1][i] - 3*p[j][i])/(2*user->dy);
239: } else if (user->st_width == 3) {
240: *p2 = fpos*(2*p[j+1][i] + 3*p[j][i] - 6*p[j-1][i] + p[j-2][i])/(6*user->dy) + fneg*(-p[j+2][i] + 6*p[j+1][i] - 3*p[j][i] - 2*p[j-1][i])/(6*user->dy);
241: }
243: /* *p2 = f*(p[j+1][i] - p[j-1][i])/user->dy;*/
244: return(0);
245: }
247: /* Diffusion term */
250: PetscErrorCode diffuse(PetscScalar **p,PetscInt i,PetscInt j,PetscReal t,PetscScalar *p_diff,AppCtx * user)
251: {
253: if (user->st_width == 1) {
254: *p_diff = user->disper_coe*((p[j-1][i] - 2*p[j][i] + p[j+1][i])/(user->dy*user->dy));
255: } else if (user->st_width == 2) {
256: *p_diff = user->disper_coe*((-p[j-2][i] + 16*p[j-1][i] - 30*p[j][i] + 16*p[j+1][i] - p[j+2][i])/(12.0*user->dy*user->dy));
257: } else if (user->st_width == 3) {
258: *p_diff = user->disper_coe*((2*p[j-3][i] - 27*p[j-2][i] + 270*p[j-1][i] - 490*p[j][i] + 270*p[j+1][i] - 27*p[j+2][i] + 2*p[j+3][i])/(180.0*user->dy*user->dy));
259: }
260: return(0);
261: }
265: PetscErrorCode IFunction(TS ts,PetscReal t,Vec X,Vec Xdot,Vec F,void *ctx)
266: {
268: AppCtx *user=(AppCtx*)ctx;
269: DM cda;
270: DMDACoor2d **coors;
271: PetscScalar **p,**f,**pdot;
272: PetscInt i,j;
273: PetscInt xs,ys,xm,ym,M,N;
274: Vec localX,gc,localXdot;
275: PetscScalar p_adv1,p_adv2,p_diff;
278: DMDAGetInfo(user->da,NULL,&M,&N,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
279: DMGetCoordinateDM(user->da,&cda);
280: DMDAGetCorners(cda,&xs,&ys,0,&xm,&ym,0);
282: DMGetLocalVector(user->da,&localX);
283: DMGetLocalVector(user->da,&localXdot);
285: DMGlobalToLocalBegin(user->da,X,INSERT_VALUES,localX);
286: DMGlobalToLocalEnd(user->da,X,INSERT_VALUES,localX);
287: DMGlobalToLocalBegin(user->da,Xdot,INSERT_VALUES,localXdot);
288: DMGlobalToLocalEnd(user->da,Xdot,INSERT_VALUES,localXdot);
290: DMGetCoordinatesLocal(user->da,&gc);
292: DMDAVecGetArrayRead(cda,gc,&coors);
293: DMDAVecGetArrayRead(user->da,localX,&p);
294: DMDAVecGetArrayRead(user->da,localXdot,&pdot);
295: DMDAVecGetArray(user->da,F,&f);
297: user->disper_coe = PetscPowScalar((user->lambda*user->ws)/(2*user->H),2)*user->q*(1.0-PetscExpScalar(-t/user->lambda));
298: for (i=xs; i < xs+xm; i++) {
299: for (j=ys; j < ys+ym; j++) {
300: adv1(p,coors[j][i].y,i,j,M,&p_adv1,user);
301: adv2(p,coors[j][i].x,i,j,N,&p_adv2,user);
302: diffuse(p,i,j,t,&p_diff,user);
303: f[j][i] = -p_adv1 - p_adv2 + p_diff - pdot[j][i];
304: }
305: }
306: DMDAVecRestoreArrayRead(user->da,localX,&p);
307: DMDAVecRestoreArrayRead(user->da,localX,&pdot);
308: DMRestoreLocalVector(user->da,&localX);
309: DMRestoreLocalVector(user->da,&localXdot);
310: DMDAVecRestoreArray(user->da,F,&f);
311: DMDAVecRestoreArrayRead(cda,gc,&coors);
313: return(0);
314: }
318: PetscErrorCode IJacobian(TS ts,PetscReal t,Vec X,Vec Xdot,PetscReal a,Mat J,Mat Jpre,void *ctx)
319: {
321: AppCtx *user=(AppCtx*)ctx;
322: DM cda;
323: DMDACoor2d **coors;
324: PetscInt i,j;
325: PetscInt xs,ys,xm,ym,M,N;
326: Vec gc;
327: PetscScalar val[5],xi,yi;
328: MatStencil row,col[5];
329: PetscScalar c1,c3,c5,c1pos,c1neg,c3pos,c3neg;
332: DMDAGetInfo(user->da,NULL,&M,&N,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
333: DMGetCoordinateDM(user->da,&cda);
334: DMDAGetCorners(cda,&xs,&ys,0,&xm,&ym,0);
336: DMGetCoordinatesLocal(user->da,&gc);
337: DMDAVecGetArrayRead(cda,gc,&coors);
338: for (i=xs; i < xs+xm; i++) {
339: for (j=ys; j < ys+ym; j++) {
340: PetscInt nc = 0;
341: xi = coors[j][i].x; yi = coors[j][i].y;
342: row.i = i; row.j = j;
343: c1 = (yi-user->ws)/user->dx;
344: c1pos = PetscMax(c1,0);
345: c1neg = PetscMin(c1,0);
346: c3 = (user->ws/(2.0*user->H))*(user->PM_min - user->Pmax*PetscSinScalar(xi))/user->dy;
347: c3pos = PetscMax(c3,0);
348: c3neg = PetscMin(c3,0);
349: c5 = (PetscPowScalar((user->lambda*user->ws)/(2*user->H),2)*user->q*(1.0-PetscExpScalar(-t/user->lambda)))/(user->dy*user->dy);
350: col[nc].i = i-1; col[nc].j = j; val[nc++] = c1pos;
351: col[nc].i = i+1; col[nc].j = j; val[nc++] = -c1neg;
352: col[nc].i = i; col[nc].j = j-1; val[nc++] = c3pos + c5;
353: col[nc].i = i; col[nc].j = j+1; val[nc++] = -c3neg + c5;
354: col[nc].i = i; col[nc].j = j; val[nc++] = -c1pos + c1neg -c3pos + c3neg -2*c5 -a;
355: MatSetValuesStencil(Jpre,1,&row,nc,col,val,INSERT_VALUES);
356: }
357: }
358: DMDAVecRestoreArrayRead(cda,gc,&coors);
360: MatAssemblyBegin(Jpre,MAT_FINAL_ASSEMBLY);
361: MatAssemblyEnd(Jpre,MAT_FINAL_ASSEMBLY);
362: if (J != Jpre) {
363: MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);
364: MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);
365: }
366: return(0);
367: }
373: PetscErrorCode Parameter_settings(AppCtx *user)
374: {
376: PetscBool flg;
380: /* Set default parameters */
381: user->ws = 1.0;
382: user->H = 5.0;
383: user->Pmax = 2.1;
384: user->PM_min = 1.0;
385: user->lambda = 0.1;
386: user->q = 1.0;
387: user->mux = PetscAsinScalar(user->PM_min/user->Pmax);
388: user->sigmax = 0.1;
389: user->sigmay = 0.1;
390: user->rho = 0.0;
391: user->xmin = -PETSC_PI;
392: user->xmax = PETSC_PI;
393: user->bx = DM_BOUNDARY_PERIODIC;
394: user->by = DM_BOUNDARY_MIRROR;
395: user->nonoiseinitial = PETSC_FALSE;
397: /*
398: ymin of -3 seems to let the unstable solution move up and leave a zero in its wake
399: with an ymin of -1 the wake is never exactly zero
400: */
401: user->ymin = -3.0;
402: user->ymax = 10.0;
403: user->st_width = 1;
405: PetscOptionsGetScalar(NULL,NULL,"-ws",&user->ws,&flg);
406: PetscOptionsGetScalar(NULL,NULL,"-Inertia",&user->H,&flg);
407: PetscOptionsGetScalar(NULL,NULL,"-Pmax",&user->Pmax,&flg);
408: PetscOptionsGetScalar(NULL,NULL,"-PM_min",&user->PM_min,&flg);
409: PetscOptionsGetScalar(NULL,NULL,"-lambda",&user->lambda,&flg);
410: PetscOptionsGetScalar(NULL,NULL,"-q",&user->q,&flg);
411: PetscOptionsGetScalar(NULL,NULL,"-mux",&user->mux,&flg);
412: PetscOptionsGetScalar(NULL,NULL,"-sigmax",&user->sigmax,&flg);
413: PetscOptionsGetScalar(NULL,NULL,"-muy",&user->muy,&flg);
414: if (flg == 0) {
415: user->muy = user->ws;
416: }
417: PetscOptionsGetScalar(NULL,NULL,"-sigmay",&user->sigmay,&flg);
418: PetscOptionsGetScalar(NULL,NULL,"-rho",&user->rho,&flg);
419: PetscOptionsGetScalar(NULL,NULL,"-xmin",&user->xmin,&flg);
420: PetscOptionsGetScalar(NULL,NULL,"-xmax",&user->xmax,&flg);
421: PetscOptionsGetScalar(NULL,NULL,"-ymin",&user->ymin,&flg);
422: PetscOptionsGetScalar(NULL,NULL,"-ymax",&user->ymax,&flg);
423: PetscOptionsGetInt(NULL,NULL,"-stencil_width",&user->st_width,&flg);
424: PetscOptionsGetEnum(NULL,NULL,"-bx",DMBoundaryTypes,(PetscEnum*)&user->bx,&flg);
425: PetscOptionsGetEnum(NULL,NULL,"-by",DMBoundaryTypes,(PetscEnum*)&user->by,&flg);
426: PetscOptionsGetBool(NULL,NULL,"-nonoiseinitial",&user->nonoiseinitial,&flg);
428: return(0);
429: }