Actual source code: ex17.c

  2: static char help[] = "Solves a linear system with KSP.  This problem is\n\
  3: intended to test the complex numbers version of various solvers.\n\n";

 5:  #include petscksp.h

  7: typedef enum {TEST_1,TEST_2,TEST_3,HELMHOLTZ_1,HELMHOLTZ_2} TestType;

 12: int main(int argc,char **args)
 13: {
 14:   Vec            x,b,u;      /* approx solution, RHS, exact solution */
 15:   Mat            A;            /* linear system matrix */
 16:   KSP            ksp;         /* KSP context */
 18:   PetscInt       n = 10,its, dim,p = 1,use_random;
 19:   PetscScalar    none = -1.0,pfive = 0.5;
 20:   PetscReal      norm;
 21:   PetscRandom    rctx;
 22:   TestType       type;
 23:   PetscTruth     flg;

 25:   PetscInitialize(&argc,&args,(char *)0,help);
 26:   PetscOptionsGetInt(PETSC_NULL,"-n",&n,PETSC_NULL);
 27:   PetscOptionsGetInt(PETSC_NULL,"-p",&p,PETSC_NULL);
 28:   switch (p) {
 29:     case 1:  type = TEST_1;      dim = n;   break;
 30:     case 2:  type = TEST_2;      dim = n;   break;
 31:     case 3:  type = TEST_3;      dim = n;   break;
 32:     case 4:  type = HELMHOLTZ_1; dim = n*n; break;
 33:     case 5:  type = HELMHOLTZ_2; dim = n*n; break;
 34:     default: type = TEST_1;      dim = n;
 35:   }

 37:   /* Create vectors */
 38:   VecCreate(PETSC_COMM_WORLD,&x);
 39:   VecSetSizes(x,PETSC_DECIDE,dim);
 40:   VecSetFromOptions(x);
 41:   VecDuplicate(x,&b);
 42:   VecDuplicate(x,&u);

 44:   use_random = 1;
 45:   PetscOptionsHasName(PETSC_NULL,"-norandom",&flg);
 46:   if (flg) {
 47:     use_random = 0;
 48:     VecSet(u,pfive);
 49:   } else {
 50:     PetscRandomCreate(PETSC_COMM_WORLD,RANDOM_DEFAULT,&rctx);
 51:     VecSetRandom(u,rctx);
 52:   }

 54:   /* Create and assemble matrix */
 55:   MatCreate(PETSC_COMM_WORLD,&A);
 56:   MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,dim,dim);
 57:   MatSetFromOptions(A);
 58:   FormTestMatrix(A,n,type);
 59:   MatMult(A,u,b);
 60:   PetscOptionsHasName(PETSC_NULL,"-printout",&flg);
 61:   if (flg) {
 62:     MatView(A,PETSC_VIEWER_STDOUT_WORLD);
 63:     VecView(u,PETSC_VIEWER_STDOUT_WORLD);
 64:     VecView(b,PETSC_VIEWER_STDOUT_WORLD);
 65:   }

 67:   /* Create KSP context; set operators and options; solve linear system */
 68:   KSPCreate(PETSC_COMM_WORLD,&ksp);
 69:   KSPSetOperators(ksp,A,A,DIFFERENT_NONZERO_PATTERN);
 70:   KSPSetFromOptions(ksp);
 71:   KSPSolve(ksp,b,x);
 72:   KSPView(ksp,PETSC_VIEWER_STDOUT_WORLD);

 74:   /* Check error */
 75:   VecAXPY(x,none,u);
 76:   VecNorm(x,NORM_2,&norm);
 77:   KSPGetIterationNumber(ksp,&its);
 78:   PetscPrintf(PETSC_COMM_WORLD,"Norm of error %A,Iterations %D\n",norm,its);

 80:   /* Free work space */
 81:   VecDestroy(x); VecDestroy(u);
 82:   VecDestroy(b); MatDestroy(A);
 83:   if (use_random) {PetscRandomDestroy(rctx);}
 84:   KSPDestroy(ksp);
 85:   PetscFinalize();
 86:   return 0;
 87: }

 91: PetscErrorCode FormTestMatrix(Mat A,PetscInt n,TestType type)
 92: {
 93: #if !defined(PETSC_USE_COMPLEX)
 94:   SETERRQ(1,"FormTestMatrix: These problems require complex numbers.");
 95: #else

 97:   PetscScalar    val[5];
 99:   PetscInt       i,j,I,J,col[5],Istart,Iend;

101:   MatGetOwnershipRange(A,&Istart,&Iend);
102:   if (type == TEST_1) {
103:     val[0] = 1.0; val[1] = 4.0; val[2] = -2.0;
104:     for (i=1; i<n-1; i++) {
105:       col[0] = i-1; col[1] = i; col[2] = i+1;
106:       MatSetValues(A,1,&i,3,col,val,INSERT_VALUES);
107:     }
108:     i = n-1; col[0] = n-2; col[1] = n-1;
109:     MatSetValues(A,1,&i,2,col,val,INSERT_VALUES);
110:     i = 0; col[0] = 0; col[1] = 1; val[0] = 4.0; val[1] = -2.0;
111:     MatSetValues(A,1,&i,2,col,val,INSERT_VALUES);
112:   }
113:   else if (type == TEST_2) {
114:     val[0] = 1.0; val[1] = 0.0; val[2] = 2.0; val[3] = 1.0;
115:     for (i=2; i<n-1; i++) {
116:       col[0] = i-2; col[1] = i-1; col[2] = i; col[3] = i+1;
117:       MatSetValues(A,1,&i,4,col,val,INSERT_VALUES);
118:     }
119:     i = n-1; col[0] = n-3; col[1] = n-2; col[2] = n-1;
120:     MatSetValues(A,1,&i,3,col,val,INSERT_VALUES);
121:     i = 1; col[0] = 0; col[1] = 1; col[2] = 2;
122:     MatSetValues(A,1,&i,3,col,&val[1],INSERT_VALUES);
123:     i = 0;
124:     MatSetValues(A,1,&i,2,col,&val[2],INSERT_VALUES);
125:   }
126:   else if (type == TEST_3) {
127:     val[0] = PETSC_i * 2.0;
128:     val[1] = 4.0; val[2] = 0.0; val[3] = 1.0; val[4] = 0.7;
129:     for (i=1; i<n-3; i++) {
130:       col[0] = i-1; col[1] = i; col[2] = i+1; col[3] = i+2; col[4] = i+3;
131:       MatSetValues(A,1,&i,5,col,val,INSERT_VALUES);
132:     }
133:     i = n-3; col[0] = n-4; col[1] = n-3; col[2] = n-2; col[3] = n-1;
134:     MatSetValues(A,1,&i,4,col,val,INSERT_VALUES);
135:     i = n-2; col[0] = n-3; col[1] = n-2; col[2] = n-1;
136:     MatSetValues(A,1,&i,3,col,val,INSERT_VALUES);
137:     i = n-1; col[0] = n-2; col[1] = n-1;
138:     MatSetValues(A,1,&i,2,col,val,INSERT_VALUES);
139:     i = 0; col[0] = 0; col[1] = 1; col[2] = 2; col[3] = 3;
140:     MatSetValues(A,1,&i,4,col,&val[1],INSERT_VALUES);
141:   }
142:   else if (type == HELMHOLTZ_1) {
143:     /* Problem domain: unit square: (0,1) x (0,1)
144:        Solve Helmholtz equation:
145:           -delta u - sigma1*u + i*sigma2*u = f, 
146:            where delta = Laplace operator
147:        Dirichlet b.c.'s on all sides
148:      */
149:     PetscRandom rctx;
150:     PetscReal   h2,sigma1 = 5.0;
151:     PetscScalar sigma2;
152:     PetscOptionsGetReal(PETSC_NULL,"-sigma1",&sigma1,PETSC_NULL);
153:     PetscRandomCreate(PETSC_COMM_WORLD,RANDOM_DEFAULT_IMAGINARY,&rctx);
154:     h2 = 1.0/((n+1)*(n+1));
155:     for (I=Istart; I<Iend; I++) {
156:       *val = -1.0; i = I/n; j = I - i*n;
157:       if (i>0) {
158:         J = I-n; MatSetValues(A,1,&I,1,&J,val,ADD_VALUES);}
159:       if (i<n-1) {
160:         J = I+n; MatSetValues(A,1,&I,1,&J,val,ADD_VALUES);}
161:       if (j>0) {
162:         J = I-1; MatSetValues(A,1,&I,1,&J,val,ADD_VALUES);}
163:       if (j<n-1) {
164:         J = I+1; MatSetValues(A,1,&I,1,&J,val,ADD_VALUES);}
165:       PetscRandomGetValue(rctx,&sigma2);
166:       *val = 4.0 - sigma1*h2 + sigma2*h2;
167:       MatSetValues(A,1,&I,1,&I,val,ADD_VALUES);
168:     }
169:     PetscRandomDestroy(rctx);
170:   }
171:   else if (type == HELMHOLTZ_2) {
172:     /* Problem domain: unit square: (0,1) x (0,1)
173:        Solve Helmholtz equation:
174:           -delta u - sigma1*u = f, 
175:            where delta = Laplace operator
176:        Dirichlet b.c.'s on 3 sides
177:        du/dn = i*alpha*u on (1,y), 0<y<1
178:      */
179:     PetscReal   h2,sigma1 = 200.0;
180:     PetscScalar alpha_h;
181:     PetscOptionsGetReal(PETSC_NULL,"-sigma1",&sigma1,PETSC_NULL);
182:     h2 = 1.0/((n+1)*(n+1));
183:     alpha_h = (PETSC_i * 10.0) / (PetscReal)(n+1);  /* alpha_h = alpha * h */
184:     for (I=Istart; I<Iend; I++) {
185:       *val = -1.0; i = I/n; j = I - i*n;
186:       if (i>0) {
187:         J = I-n; MatSetValues(A,1,&I,1,&J,val,ADD_VALUES);}
188:       if (i<n-1) {
189:         J = I+n; MatSetValues(A,1,&I,1,&J,val,ADD_VALUES);}
190:       if (j>0) {
191:         J = I-1; MatSetValues(A,1,&I,1,&J,val,ADD_VALUES);}
192:       if (j<n-1) {
193:         J = I+1; MatSetValues(A,1,&I,1,&J,val,ADD_VALUES);}
194:       *val = 4.0 - sigma1*h2;
195:       if (!((I+1)%n)) *val += alpha_h;
196:       MatSetValues(A,1,&I,1,&I,val,ADD_VALUES);
197:     }
198:   }
199:   else SETERRQ(1,"FormTestMatrix: unknown test matrix type");

201:   MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
202:   MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
203: #endif

205:   return 0;
206: }