Actual source code: ex19.c
1: /* "$Id: ex19.c,v 1.12 2001/08/07 21:30:50 bsmith Exp $" */
3: static char help[] ="Solvers Laplacian with multigrid, bad way.n
4: -mx <xg>, where <xg> = number of grid points in the x-directionn
5: -my <yg>, where <yg> = number of grid points in the y-directionn
6: -Nx <npx>, where <npx> = number of processors in the x-directionn
7: -Ny <npy>, where <npy> = number of processors in the y-directionnn";
9: /*
10: This problem is modeled by
11: the partial differential equation
12:
13: -Laplacian u = g, 0 < x,y < 1,
14:
15: with boundary conditions
16:
17: u = 0 for x = 0, x = 1, y = 0, y = 1.
18:
19: A finite difference approximation with the usual 5-point stencil
20: is used to discretize the boundary value problem to obtain a nonlinear
21: system of equations.
22: */
24: #include petscsles.h
25: #include petscda.h
26: #include petscmg.h
28: /* User-defined application contexts */
30: typedef struct {
31: int mx,my; /* number grid points in x and y direction */
32: Vec localX,localF; /* local vectors with ghost region */
33: DA da;
34: Vec x,b,r; /* global vectors */
35: Mat J; /* Jacobian on grid */
36: } GridCtx;
38: typedef struct {
39: GridCtx fine;
40: GridCtx coarse;
41: SLES sles_coarse;
42: int ratio;
43: Mat I; /* interpolation from coarse to fine */
44: } AppCtx;
46: #define COARSE_LEVEL 0
47: #define FINE_LEVEL 1
49: extern int FormJacobian_Grid(AppCtx *,GridCtx *,Mat *);
51: /*
52: Mm_ratio - ration of grid lines between fine and coarse grids.
53: */
54: int main(int argc,char **argv)
55: {
56: AppCtx user;
57: int ierr,its,N,n,Nx = PETSC_DECIDE,Ny = PETSC_DECIDE;
58: int size,nlocal,Nlocal;
59: SLES sles,sles_fine;
60: PC pc;
61: PetscScalar one = 1.0;
63: PetscInitialize(&argc,&argv,PETSC_NULL,help);
65: user.ratio = 2;
66: user.coarse.mx = 5; user.coarse.my = 5;
67: PetscOptionsGetInt(PETSC_NULL,"-Mx",&user.coarse.mx,PETSC_NULL);
68: PetscOptionsGetInt(PETSC_NULL,"-My",&user.coarse.my,PETSC_NULL);
69: PetscOptionsGetInt(PETSC_NULL,"-ratio",&user.ratio,PETSC_NULL);
70: user.fine.mx = user.ratio*(user.coarse.mx-1)+1; user.fine.my = user.ratio*(user.coarse.my-1)+1;
72: PetscPrintf(PETSC_COMM_WORLD,"Coarse grid size %d by %dn",user.coarse.mx,user.coarse.my);
73: PetscPrintf(PETSC_COMM_WORLD,"Fine grid size %d by %dn",user.fine.mx,user.fine.my);
75: n = user.fine.mx*user.fine.my; N = user.coarse.mx*user.coarse.my;
77: MPI_Comm_size(PETSC_COMM_WORLD,&size);
78: PetscOptionsGetInt(PETSC_NULL,"-Nx",&Nx,PETSC_NULL);
79: PetscOptionsGetInt(PETSC_NULL,"-Ny",&Ny,PETSC_NULL);
81: /* Set up distributed array for fine grid */
82: DACreate2d(PETSC_COMM_WORLD,DA_NONPERIODIC,DA_STENCIL_STAR,user.fine.mx,
83: user.fine.my,Nx,Ny,1,1,PETSC_NULL,PETSC_NULL,&user.fine.da);
84: DACreateGlobalVector(user.fine.da,&user.fine.x);
85: VecDuplicate(user.fine.x,&user.fine.r);
86: VecDuplicate(user.fine.x,&user.fine.b);
87: VecGetLocalSize(user.fine.x,&nlocal);
88: DACreateLocalVector(user.fine.da,&user.fine.localX);
89: VecDuplicate(user.fine.localX,&user.fine.localF);
90: MatCreateMPIAIJ(PETSC_COMM_WORLD,nlocal,nlocal,n,n,5,PETSC_NULL,3,PETSC_NULL,&user.fine.J);
92: /* Set up distributed array for coarse grid */
93: DACreate2d(PETSC_COMM_WORLD,DA_NONPERIODIC,DA_STENCIL_STAR,user.coarse.mx,
94: user.coarse.my,Nx,Ny,1,1,PETSC_NULL,PETSC_NULL,&user.coarse.da);
95: DACreateGlobalVector(user.coarse.da,&user.coarse.x);
96: VecDuplicate(user.coarse.x,&user.coarse.b);
97: VecGetLocalSize(user.coarse.x,&Nlocal);
98: DACreateLocalVector(user.coarse.da,&user.coarse.localX);
99: VecDuplicate(user.coarse.localX,&user.coarse.localF);
100: MatCreateMPIAIJ(PETSC_COMM_WORLD,Nlocal,Nlocal,N,N,5,PETSC_NULL,3,PETSC_NULL,&user.coarse.J);
102: /* Create linear solver */
103: SLESCreate(PETSC_COMM_WORLD,&sles);
105: /* set two level additive Schwarz preconditioner */
106: SLESGetPC(sles,&pc);
107: PCSetType(pc,PCMG);
108: MGSetLevels(pc,2,PETSC_NULL);
109: MGSetType(pc,MGADDITIVE);
111: FormJacobian_Grid(&user,&user.coarse,&user.coarse.J);
112: FormJacobian_Grid(&user,&user.fine,&user.fine.J);
114: /* Create coarse level */
115: MGGetCoarseSolve(pc,&user.sles_coarse);
116: SLESSetOptionsPrefix(user.sles_coarse,"coarse_");
117: SLESSetFromOptions(user.sles_coarse);
118: SLESSetOperators(user.sles_coarse,user.coarse.J,user.coarse.J,DIFFERENT_NONZERO_PATTERN);
119: MGSetX(pc,COARSE_LEVEL,user.coarse.x);
120: MGSetRhs(pc,COARSE_LEVEL,user.coarse.b);
122: /* Create fine level */
123: MGGetSmoother(pc,FINE_LEVEL,&sles_fine);
124: SLESSetOptionsPrefix(sles_fine,"fine_");
125: SLESSetFromOptions(sles_fine);
126: SLESSetOperators(sles_fine,user.fine.J,user.fine.J,DIFFERENT_NONZERO_PATTERN);
127: MGSetR(pc,FINE_LEVEL,user.fine.r);
128: MGSetResidual(pc,FINE_LEVEL,MGDefaultResidual,user.fine.J);
130: /* Create interpolation between the levels */
131: DAGetInterpolation(user.coarse.da,user.fine.da,&user.I,PETSC_NULL);
132: MGSetInterpolate(pc,FINE_LEVEL,user.I);
133: MGSetRestriction(pc,FINE_LEVEL,user.I);
135: SLESSetOperators(sles,user.fine.J,user.fine.J,DIFFERENT_NONZERO_PATTERN);
137: VecSet(&one,user.fine.b);
138: {
139: PetscRandom rand;
140: PetscRandomCreate(PETSC_COMM_WORLD,RANDOM_DEFAULT,&rand);
141: VecSetRandom(rand,user.fine.b);
142: PetscRandomDestroy(rand);
143: }
145: /* Set options, then solve nonlinear system */
146: SLESSetFromOptions(sles);
148: SLESSolve(sles,user.fine.b,user.fine.x,&its);
149: PetscPrintf(PETSC_COMM_WORLD,"Number of iterations = %dn",its);
151: /* Free data structures */
152: MatDestroy(user.fine.J);
153: VecDestroy(user.fine.x);
154: VecDestroy(user.fine.r);
155: VecDestroy(user.fine.b);
156: DADestroy(user.fine.da);
157: VecDestroy(user.fine.localX);
158: VecDestroy(user.fine.localF);
160: MatDestroy(user.coarse.J);
161: VecDestroy(user.coarse.x);
162: VecDestroy(user.coarse.b);
163: DADestroy(user.coarse.da);
164: VecDestroy(user.coarse.localX);
165: VecDestroy(user.coarse.localF);
167: SLESDestroy(sles);
168: MatDestroy(user.I);
169: PetscFinalize();
171: return 0;
172: }
174: int FormJacobian_Grid(AppCtx *user,GridCtx *grid,Mat *J)
175: {
176: Mat jac = *J;
177: int ierr,i,j,row,mx,my,xs,ys,xm,ym,Xs,Ys,Xm,Ym,col[5];
178: int nloc,*ltog,grow;
179: PetscScalar two = 2.0,one = 1.0,v[5],hx,hy,hxdhy,hydhx,value;
181: mx = grid->mx; my = grid->my;
182: hx = one/(PetscReal)(mx-1); hy = one/(PetscReal)(my-1);
183: hxdhy = hx/hy; hydhx = hy/hx;
185: /* Get ghost points */
186: DAGetCorners(grid->da,&xs,&ys,0,&xm,&ym,0);
187: DAGetGhostCorners(grid->da,&Xs,&Ys,0,&Xm,&Ym,0);
188: DAGetGlobalIndices(grid->da,&nloc,<og);
190: /* Evaluate Jacobian of function */
191: for (j=ys; j<ys+ym; j++) {
192: row = (j - Ys)*Xm + xs - Xs - 1;
193: for (i=xs; i<xs+xm; i++) {
194: row++;
195: grow = ltog[row];
196: if (i > 0 && i < mx-1 && j > 0 && j < my-1) {
197: v[0] = -hxdhy; col[0] = ltog[row - Xm];
198: v[1] = -hydhx; col[1] = ltog[row - 1];
199: v[2] = two*(hydhx + hxdhy); col[2] = grow;
200: v[3] = -hydhx; col[3] = ltog[row + 1];
201: v[4] = -hxdhy; col[4] = ltog[row + Xm];
202: MatSetValues(jac,1,&grow,5,col,v,INSERT_VALUES);
203: } else if ((i > 0 && i < mx-1) || (j > 0 && j < my-1)){
204: value = .5*two*(hydhx + hxdhy);
205: MatSetValues(jac,1,&grow,1,&grow,&value,INSERT_VALUES);
206: } else {
207: value = .25*two*(hydhx + hxdhy);
208: MatSetValues(jac,1,&grow,1,&grow,&value,INSERT_VALUES);
209: }
210: }
211: }
212: MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);
213: MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);
215: return 0;
216: }