Actual source code: ex50.c
petsc-3.3-p7 2013-05-11
1: /* DM/KSP solving a system of linear equations.
2: Poisson equation in 2D:
4: div(grad p) = f, 0 < x,y < 1
5: with
6: forcing function f = -cos(m*pi*x)*cos(n*pi*y),
7: Neuman boundary conditions
8: dp/dx = 0 for x = 0, x = 1.
9: dp/dy = 0 for y = 0, y = 1.
11: Contributed by Michael Boghosian <boghmic@iit.edu>, 2008,
12: based on petsc/src/ksp/ksp/examples/tutorials/ex29.c and ex32.c
14: Example of Usage:
15: ./ex50 -mglevels 3 -ksp_monitor -M 3 -N 3 -ksp_view -da_view_draw -draw_pause -1
16: ./ex50 -M 100 -N 100 -mglevels 1 -mg_levels_0_pc_factor_levels <ilu_levels> -ksp_monitor -cmp_solu
17: ./ex50 -M 100 -N 100 -mglevels 1 -mg_levels_0_pc_type lu -mg_levels_0_pc_factor_shift_type NONZERO -ksp_monitor -cmp_solu
18: mpiexec -n 4 ./ex50 -M 3 -N 3 -ksp_monitor -ksp_view -mglevels 10 -log_summary
19: */
21: static char help[] = "Solves 2D Poisson equation using multigrid.\n\n";
23: #include <petscdmda.h>
24: #include <petscksp.h>
25: #include <petscpcmg.h>
26: #include <petscsys.h>
27: #include <petscvec.h>
29: extern PetscErrorCode ComputeJacobian(KSP,Mat,Mat,MatStructure*,void*);
30: extern PetscErrorCode ComputeRHS(KSP,Vec,void*);
31: extern PetscErrorCode ComputeTrueSolution(DM, Vec);
32: extern PetscErrorCode VecView_VTK(Vec, const char [], const char []);
34: typedef enum {DIRICHLET, NEUMANN} BCType;
36: typedef struct {
37: PetscScalar uu, tt;
38: BCType bcType;
39: } UserContext;
43: int main(int argc,char **argv)
44: {
45: KSP ksp;
46: DM da;
47: UserContext user;
48: PetscInt bc;
50:
51: PetscInitialize(&argc,&argv,(char *)0,help);
52: KSPCreate(PETSC_COMM_WORLD,&ksp);
53: DMDACreate2d(PETSC_COMM_WORLD, DMDA_BOUNDARY_NONE, DMDA_BOUNDARY_NONE,DMDA_STENCIL_STAR,-11,-11,PETSC_DECIDE,PETSC_DECIDE,1,1,PETSC_NULL,PETSC_NULL,&da);
54: KSPSetDM(ksp,(DM)da);
55: DMSetApplicationContext(da,&user);
57: user.uu = 1.0;
58: user.tt = 1.0;
59: bc = (PetscInt)NEUMANN; // Use Neumann Boundary Conditions
60: user.bcType = (BCType)bc;
62:
63: KSPSetComputeRHS(ksp,ComputeRHS,&user);
64: KSPSetComputeOperators(ksp,ComputeJacobian,&user);
65: KSPSetFromOptions(ksp);
66: KSPSolve(ksp,PETSC_NULL,PETSC_NULL);
68: DMDestroy(&da);
69: KSPDestroy(&ksp);
70: PetscFinalize();
71: return 0;
72: }
76: PetscErrorCode ComputeRHS(KSP ksp,Vec b,void *ctx)
77: {
78: UserContext *user = (UserContext*)ctx;
80: PetscInt i, j, M, N, xm ,ym ,xs, ys;
81: PetscScalar Hx, Hy, pi, uu, tt;
82: PetscScalar **array;
83: DM da;
86: KSPGetDM(ksp,&da);
87: DMDAGetInfo(da, 0, &M, &N, 0,0,0,0,0,0,0,0,0,0);
88: uu = user->uu; tt = user->tt;
89: pi = 4*atan(1.0);
90: Hx = 1.0/(PetscReal)(M);
91: Hy = 1.0/(PetscReal)(N);
93: DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0); // Fine grid
94: //printf(" M N: %d %d; xm ym: %d %d; xs ys: %d %d\n",M,N,xm,ym,xs,ys);
95: DMDAVecGetArray(da, b, &array);
96: for (j=ys; j<ys+ym; j++){
97: for(i=xs; i<xs+xm; i++){
98: array[j][i] = -PetscCosScalar(uu*pi*((PetscReal)i+0.5)*Hx)*cos(tt*pi*((PetscReal)j+0.5)*Hy)*Hx*Hy;
99: }
100: }
101: DMDAVecRestoreArray(da, b, &array);
102: VecAssemblyBegin(b);
103: VecAssemblyEnd(b);
105: /* force right hand side to be consistent for singular matrix */
106: /* note this is really a hack, normally the model would provide you with a consistent right handside */
107: if (user->bcType == NEUMANN) {
108: MatNullSpace nullspace;
110: MatNullSpaceCreate(PETSC_COMM_WORLD,PETSC_TRUE,0,0,&nullspace);
111: MatNullSpaceRemove(nullspace,b,PETSC_NULL);
112: MatNullSpaceDestroy(&nullspace);
113: }
114: return(0);
115: }
119: PetscErrorCode ComputeJacobian(KSP ksp,Mat J, Mat jac,MatStructure *str,void *ctx)
120: {
121: UserContext *user = (UserContext*)ctx;
123: PetscInt i, j, M, N, xm, ym, xs, ys, num, numi, numj;
124: PetscScalar v[5], Hx, Hy, HydHx, HxdHy;
125: MatStencil row, col[5];
126: DM da;
129: KSPGetDM(ksp,&da);
130: DMDAGetInfo(da,0,&M,&N,0,0,0,0,0,0,0,0,0,0);
131: Hx = 1.0 / (PetscReal)(M);
132: Hy = 1.0 / (PetscReal)(N);
133: HxdHy = Hx/Hy;
134: HydHx = Hy/Hx;
135: DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0);
136: for (j=ys; j<ys+ym; j++){
137: for(i=xs; i<xs+xm; i++){
138: row.i = i; row.j = j;
139:
140: if (i==0 || j==0 || i==M-1 || j==N-1) {
141: if (user->bcType == DIRICHLET){
142: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Dirichlet boundary conditions not supported !\n");
143: } else if (user->bcType == NEUMANN){
144: num=0; numi=0; numj=0;
145: if (j!=0) {
146: v[num] = -HxdHy; col[num].i = i; col[num].j = j-1;
147: num++; numj++;
148: }
149: if (i!=0) {
150: v[num] = -HydHx; col[num].i = i-1; col[num].j = j;
151: num++; numi++;
152: }
153: if (i!=M-1) {
154: v[num] = -HydHx; col[num].i = i+1; col[num].j = j;
155: num++; numi++;
156: }
157: if (j!=N-1) {
158: v[num] = -HxdHy; col[num].i = i; col[num].j = j+1;
159: num++; numj++;
160: }
161: v[num] = ( (PetscReal)(numj)*HxdHy + (PetscReal)(numi)*HydHx ); col[num].i = i; col[num].j = j;
162: num++;
163: MatSetValuesStencil(jac,1,&row,num,col,v,INSERT_VALUES);
164: }
165: } else {
166: v[0] = -HxdHy; col[0].i = i; col[0].j = j-1;
167: v[1] = -HydHx; col[1].i = i-1; col[1].j = j;
168: v[2] = 2.0*(HxdHy + HydHx); col[2].i = i; col[2].j = j;
169: v[3] = -HydHx; col[3].i = i+1; col[3].j = j;
170: v[4] = -HxdHy; col[4].i = i; col[4].j = j+1;
171: MatSetValuesStencil(jac,1,&row,5,col,v,INSERT_VALUES);
172: }
173: }
174: }
175: MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);
176: MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);
177: if (user->bcType == NEUMANN) {
178: MatNullSpace nullspace;
180: MatNullSpaceCreate(PETSC_COMM_WORLD,PETSC_TRUE,0,0,&nullspace);
181: MatSetNullSpace(jac,nullspace);
182: MatNullSpaceDestroy(&nullspace);
183: }
184: return(0);
185: }