Actual source code: ex10.c

petsc-dev 2014-02-02
Report Typos and Errors
  2: static char help[] = "Reads a PETSc matrix and vector from a file and solves a linear system.\n\
  3: This version first preloads and solves a small system, then loads \n\
  4: another (larger) system and solves it as well.  This example illustrates\n\
  5: preloading of instructions with the smaller system so that more accurate\n\
  6: performance monitoring can be done with the larger one (that actually\n\
  7: is the system of interest).  See the 'Performance Hints' chapter of the\n\
  8: users manual for a discussion of preloading.  Input parameters include\n\
  9:   -f0 <input_file> : first file to load (small system)\n\
 10:   -f1 <input_file> : second file to load (larger system)\n\n\
 11:   -trans  : solve transpose system instead\n\n";
 12: /*
 13:   This code can be used to test PETSc interface to other packages.\n\
 14:   Examples of command line options:       \n\
 15:    ./ex10 -f0 <datafile> -ksp_type preonly  \n\
 16:         -help -ksp_view                  \n\
 17:         -num_numfac <num_numfac> -num_rhs <num_rhs> \n\
 18:         -ksp_type preonly -pc_type lu -pc_factor_mat_solver_package superlu or superlu_dist or mumps \n\
 19:         -ksp_type preonly -pc_type cholesky -pc_factor_mat_solver_package mumps \n\
 20:    mpiexec -n <np> ./ex10 -f0 <datafile> -ksp_type cg -pc_type asm -pc_asm_type basic -sub_pc_type icc -mat_type sbaij
 21:  \n\n";
 22: */
 23: /*T
 24:    Concepts: KSP^solving a linear system
 25:    Processors: n
 26: T*/

 28: /*
 29:   Include "petscksp.h" so that we can use KSP solvers.  Note that this file
 30:   automatically includes:
 31:      petscsys.h       - base PETSc routines   petscvec.h - vectors
 32:      petscmat.h - matrices
 33:      petscis.h     - index sets            petscksp.h - Krylov subspace methods
 34:      petscviewer.h - viewers               petscpc.h  - preconditioners
 35: */
 36: #include <petscksp.h>

 40: int main(int argc,char **args)
 41: {
 42:   KSP            ksp;             /* linear solver context */
 43:   Mat            A;               /* matrix */
 44:   Vec            x,b,u;           /* approx solution, RHS, exact solution */
 45:   PetscViewer    fd;              /* viewer */
 46:   char           file[4][PETSC_MAX_PATH_LEN];     /* input file name */
 47:   PetscBool      table     =PETSC_FALSE,flg,trans=PETSC_FALSE,initialguess = PETSC_FALSE;
 48:   PetscBool      outputSoln=PETSC_FALSE;
 50:   PetscInt       its,num_numfac,m,n,M;
 51:   PetscReal      norm;
 52:   PetscBool      preload=PETSC_TRUE,isSymmetric,cknorm=PETSC_FALSE,initialguessfile = PETSC_FALSE;
 53:   PetscMPIInt    rank;
 54:   char           initialguessfilename[PETSC_MAX_PATH_LEN];

 56:   PetscInitialize(&argc,&args,(char*)0,help);
 57:   MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
 58:   PetscOptionsGetBool(NULL,"-table",&table,NULL);
 59:   PetscOptionsGetBool(NULL,"-trans",&trans,NULL);
 60:   PetscOptionsGetBool(NULL,"-initialguess",&initialguess,NULL);
 61:   PetscOptionsGetBool(NULL,"-output_solution",&outputSoln,NULL);
 62:   PetscOptionsGetString(NULL,"-initialguessfilename",initialguessfilename,PETSC_MAX_PATH_LEN,&initialguessfile);

 64:   /*
 65:      Determine files from which we read the two linear systems
 66:      (matrix and right-hand-side vector).
 67:   */
 68:   PetscOptionsGetString(NULL,"-f",file[0],PETSC_MAX_PATH_LEN,&flg);
 69:   if (flg) {
 70:     PetscStrcpy(file[1],file[0]);
 71:     preload = PETSC_FALSE;
 72:   } else {
 73:     PetscOptionsGetString(NULL,"-f0",file[0],PETSC_MAX_PATH_LEN,&flg);
 74:     if (!flg) SETERRQ(PETSC_COMM_WORLD,1,"Must indicate binary file with the -f0 or -f option");
 75:     PetscOptionsGetString(NULL,"-f1",file[1],PETSC_MAX_PATH_LEN,&flg);
 76:     if (!flg) preload = PETSC_FALSE;   /* don't bother with second system */
 77:   }

 79:   /* -----------------------------------------------------------
 80:                   Beginning of linear solver loop
 81:      ----------------------------------------------------------- */
 82:   /*
 83:      Loop through the linear solve 2 times.
 84:       - The intention here is to preload and solve a small system;
 85:         then load another (larger) system and solve it as well.
 86:         This process preloads the instructions with the smaller
 87:         system so that more accurate performance monitoring (via
 88:         -log_summary) can be done with the larger one (that actually
 89:         is the system of interest).
 90:   */
 91:   PetscPreLoadBegin(preload,"Load system");

 93:   /* - - - - - - - - - - - New Stage - - - - - - - - - - - - -
 94:                          Load system
 95:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

 97:   /*
 98:      Open binary file.  Note that we use FILE_MODE_READ to indicate
 99:      reading from this file.
100:   */
101:   PetscViewerBinaryOpen(PETSC_COMM_WORLD,file[PetscPreLoadIt],FILE_MODE_READ,&fd);

103:   /*
104:      Load the matrix and vector; then destroy the viewer.
105:   */
106:   MatCreate(PETSC_COMM_WORLD,&A);
107:   MatSetFromOptions(A);
108:   MatLoad(A,fd);

110:   flg  = PETSC_FALSE;
111:   PetscOptionsGetString(NULL,"-rhs",file[2],PETSC_MAX_PATH_LEN,&flg);
112:   VecCreate(PETSC_COMM_WORLD,&b);
113:   if (flg) {   /* rhs is stored in a separate file */
114:     if (file[2][0] == '0') {
115:       PetscInt    m;
116:       PetscScalar one = 1.0;
117:       PetscInfo(0,"Using vector of ones for RHS\n");
118:       MatGetLocalSize(A,&m,NULL);
119:       VecSetSizes(b,m,PETSC_DECIDE);
120:       VecSetFromOptions(b);
121:       VecSet(b,one);
122:     } else {
123:       PetscViewerDestroy(&fd);
124:       PetscViewerBinaryOpen(PETSC_COMM_WORLD,file[2],FILE_MODE_READ,&fd);
125:       VecSetFromOptions(b);
126:       VecLoad(b,fd);
127:     }
128:   } else {   /* rhs is stored in the same file as matrix */
129:     VecSetFromOptions(b);
130:     VecLoad(b,fd);
131:   }
132:   PetscViewerDestroy(&fd);

134:   /* Make A singular for testing zero-pivot of ilu factorization        */
135:   /* Example: ./ex10 -f0 <datafile> -test_zeropivot -set_row_zero -pc_factor_shift_nonzero */
136:   flg  = PETSC_FALSE;
137:   PetscOptionsGetBool(NULL, "-test_zeropivot", &flg,NULL);
138:   if (flg) {
139:     PetscInt          row,ncols;
140:     const PetscInt    *cols;
141:     const PetscScalar *vals;
142:     PetscBool         flg1=PETSC_FALSE;
143:     PetscScalar       *zeros;
144:     row  = 0;
145:     MatGetRow(A,row,&ncols,&cols,&vals);
146:     PetscMalloc(sizeof(PetscScalar)*(ncols+1),&zeros);
147:     PetscMemzero(zeros,(ncols+1)*sizeof(PetscScalar));
148:     PetscOptionsGetBool(NULL, "-set_row_zero", &flg1,NULL);
149:     if (flg1) {   /* set entire row as zero */
150:       MatSetValues(A,1,&row,ncols,cols,zeros,INSERT_VALUES);
151:     } else {   /* only set (row,row) entry as zero */
152:       MatSetValues(A,1,&row,1,&row,zeros,INSERT_VALUES);
153:     }
154:     MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
155:     MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
156:   }

158:   /* Check whether A is symmetric */
159:   flg  = PETSC_FALSE;
160:   PetscOptionsGetBool(NULL, "-check_symmetry", &flg,NULL);
161:   if (flg) {
162:     Mat Atrans;
163:     MatTranspose(A, MAT_INITIAL_MATRIX,&Atrans);
164:     MatEqual(A, Atrans, &isSymmetric);
165:     if (isSymmetric) {
166:       MatSetOption(A,MAT_SYMMETRIC,PETSC_TRUE);
167:     } else {
168:       PetscPrintf(PETSC_COMM_WORLD,"Warning: A is non-symmetric \n");
169:     }
170:     MatDestroy(&Atrans);
171:   }

173:   /*
174:      If the loaded matrix is larger than the vector (due to being padded
175:      to match the block size of the system), then create a new padded vector.
176:   */

178:   MatGetLocalSize(A,&m,&n);
179:   /*  if (m != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ, "This example is not intended for rectangular matrices (%d, %d)", m, n);*/
180:   MatGetSize(A,&M,NULL);
181:   VecGetSize(b,&m);
182:   if (M != m) {   /* Create a new vector b by padding the old one */
183:     PetscInt    j,mvec,start,end,indx;
184:     Vec         tmp;
185:     PetscScalar *bold;

187:     VecCreate(PETSC_COMM_WORLD,&tmp);
188:     VecSetSizes(tmp,n,PETSC_DECIDE);
189:     VecSetFromOptions(tmp);
190:     VecGetOwnershipRange(b,&start,&end);
191:     VecGetLocalSize(b,&mvec);
192:     VecGetArray(b,&bold);
193:     for (j=0; j<mvec; j++) {
194:       indx = start+j;
195:       VecSetValues(tmp,1,&indx,bold+j,INSERT_VALUES);
196:     }
197:     VecRestoreArray(b,&bold);
198:     VecDestroy(&b);
199:     VecAssemblyBegin(tmp);
200:     VecAssemblyEnd(tmp);
201:     b    = tmp;
202:   }

204:   MatGetVecs(A,&x,NULL);
205:   VecDuplicate(b,&u);
206:   if (initialguessfile) {
207:     PetscViewer viewer2;
208:     PetscViewerBinaryOpen(PETSC_COMM_WORLD,initialguessfilename,FILE_MODE_READ,&viewer2);
209:     VecLoad(x,viewer2);
210:     PetscViewerDestroy(&viewer2);
211:     initialguess = PETSC_TRUE;
212:   } else if (initialguess) {
213:     VecSet(x,1.0);
214:   } else {
215:     VecSet(x,0.0);
216:   }


219:   /* Check scaling in A */
220:   flg  = PETSC_FALSE;
221:   PetscOptionsGetBool(NULL, "-check_scaling", &flg,NULL);
222:   if (flg) {
223:     Vec       max, min;
224:     PetscInt  idx;
225:     PetscReal val;

227:     VecDuplicate(x, &max);
228:     VecDuplicate(x, &min);
229:     MatGetRowMaxAbs(A, max, NULL);
230:     MatGetRowMinAbs(A, min, NULL);
231:     {
232:       PetscViewer viewer;

234:       PetscViewerASCIIOpen(PETSC_COMM_WORLD, "max.data", &viewer);
235:       VecView(max, viewer);
236:       PetscViewerDestroy(&viewer);
237:       PetscViewerASCIIOpen(PETSC_COMM_WORLD, "min.data", &viewer);
238:       VecView(min, viewer);
239:       PetscViewerDestroy(&viewer);
240:     }
241:     VecView(max, PETSC_VIEWER_DRAW_WORLD);
242:     VecMax(max, &idx, &val);
243:     PetscPrintf(PETSC_COMM_WORLD, "Largest max row element %g at row %D\n", (double)val, idx);
244:     VecView(min, PETSC_VIEWER_DRAW_WORLD);
245:     VecMin(min, &idx, &val);
246:     PetscPrintf(PETSC_COMM_WORLD, "Smallest min row element %g at row %D\n", (double)val, idx);
247:     VecMin(max, &idx, &val);
248:     PetscPrintf(PETSC_COMM_WORLD, "Smallest max row element %g at row %D\n", (double)val, idx);
249:     VecPointwiseDivide(max, max, min);
250:     VecMax(max, &idx, &val);
251:     PetscPrintf(PETSC_COMM_WORLD, "Largest row ratio %g at row %D\n", (double)val, idx);
252:     VecView(max, PETSC_VIEWER_DRAW_WORLD);
253:     VecDestroy(&max);
254:     VecDestroy(&min);
255:   }

257:   /*  MatView(A,PETSC_VIEWER_STDOUT_WORLD); */
258:   /* - - - - - - - - - - - New Stage - - - - - - - - - - - - -
259:                     Setup solve for system
260:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
261:   /*
262:      Conclude profiling last stage; begin profiling next stage.
263:   */
264:   PetscPreLoadStage("KSPSetUpSolve");

266:   /*
267:      Create linear solver; set operators; set runtime options.
268:   */
269:   KSPCreate(PETSC_COMM_WORLD,&ksp);
270:   KSPSetInitialGuessNonzero(ksp,initialguess);
271:   num_numfac = 1;
272:   PetscOptionsGetInt(NULL,"-num_numfac",&num_numfac,NULL);
273:   while (num_numfac--) {
274:     PetscBool lsqr;
275:     char      str[32];
276:     PetscOptionsGetString(NULL,"-ksp_type",str,32,&lsqr);
277:     if (lsqr) {
278:       PetscStrcmp("lsqr",str,&lsqr);
279:     }
280:     if (lsqr) {
281:       Mat BtB;
282:       MatTransposeMatMult(A,A,MAT_INITIAL_MATRIX,4,&BtB);
283:       KSPSetOperators(ksp,A,BtB,SAME_NONZERO_PATTERN);
284:       MatDestroy(&BtB);
285:     } else {
286:       KSPSetOperators(ksp,A,A,SAME_NONZERO_PATTERN);
287:     }
288:     KSPSetFromOptions(ksp);

290:     /*
291:      Here we explicitly call KSPSetUp() and KSPSetUpOnBlocks() to
292:      enable more precise profiling of setting up the preconditioner.
293:      These calls are optional, since both will be called within
294:      KSPSolve() if they haven't been called already.
295:     */
296:     KSPSetUp(ksp);
297:     KSPSetUpOnBlocks(ksp);

299:     /* - - - - - - - - - - - New Stage - - - - - - - - - - - - -
300:                          Solve system
301:       - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

303:     /*
304:      Solve linear system; 
305:     */
306:     if (trans) {
307:       KSPSolveTranspose(ksp,b,x);
308:       KSPGetIterationNumber(ksp,&its);
309:     } else {
310:       PetscInt num_rhs=1;
311:       PetscOptionsGetInt(NULL,"-num_rhs",&num_rhs,NULL);
312:       cknorm = PETSC_FALSE;
313:       PetscOptionsGetBool(NULL,"-cknorm",&cknorm,NULL);
314:       while (num_rhs--) {
315:         if (num_rhs == 1) VecSet(x,0.0);
316:         KSPSolve(ksp,b,x);
317:       }
318:       KSPGetIterationNumber(ksp,&its);
319:       if (cknorm) {     /* Check error for each rhs */
320:         if (trans) {
321:           MatMultTranspose(A,x,u);
322:         } else {
323:           MatMult(A,x,u);
324:         }
325:         VecAXPY(u,-1.0,b);
326:         VecNorm(u,NORM_2,&norm);
327:         PetscPrintf(PETSC_COMM_WORLD,"  Number of iterations = %3D\n",its);
328:         if (norm < 1.e-12) {
329:           PetscPrintf(PETSC_COMM_WORLD,"  Residual norm < 1.e-12\n");
330:         } else {
331:           PetscPrintf(PETSC_COMM_WORLD,"  Residual norm %g\n",(double)norm);
332:         }
333:       }
334:     }   /* while (num_rhs--) */

336:     /* - - - - - - - - - - - New Stage - - - - - - - - - - - - -
337:           Check error, print output, free data structures.
338:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

340:     /*
341:        Check error
342:     */
343:     if (trans) {
344:       MatMultTranspose(A,x,u);
345:     } else {
346:       MatMult(A,x,u);
347:     }
348:     VecAXPY(u,-1.0,b);
349:     VecNorm(u,NORM_2,&norm);
350:     /*
351:      Write output (optinally using table for solver details).
352:       - PetscPrintf() handles output for multiprocessor jobs
353:         by printing from only one processor in the communicator.
354:       - KSPView() prints information about the linear solver.
355:     */
356:     if (table) {
357:       char        *matrixname,kspinfo[120];
358:       PetscViewer viewer;

360:       /*
361:        Open a string viewer; then write info to it.
362:       */
363:       PetscViewerStringOpen(PETSC_COMM_WORLD,kspinfo,120,&viewer);
364:       KSPView(ksp,viewer);
365:       PetscStrrchr(file[PetscPreLoadIt],'/',&matrixname);
366:       PetscPrintf(PETSC_COMM_WORLD,"%-8.8s %3D %2.0e %s \n",matrixname,its,norm,kspinfo);

368:       /*
369:         Destroy the viewer
370:       */
371:       PetscViewerDestroy(&viewer);
372:     } else {
373:       PetscPrintf(PETSC_COMM_WORLD,"Number of iterations = %3D\n",its);
374:       if (norm < 1.e-12) {
375:         PetscPrintf(PETSC_COMM_WORLD,"  Residual norm < 1.e-12\n");
376:       } else {
377:         PetscPrintf(PETSC_COMM_WORLD,"Residual norm %g\n",(double)norm);
378:       }
379:     }
380:     PetscOptionsGetString(NULL,"-solution",file[3],PETSC_MAX_PATH_LEN,&flg);
381:     if (flg) {
382:       PetscViewer viewer;
383:       Vec         xstar;
384:       PetscReal   norm;

386:       PetscViewerBinaryOpen(PETSC_COMM_WORLD,file[3],FILE_MODE_READ,&viewer);
387:       VecCreate(PETSC_COMM_WORLD,&xstar);
388:       VecLoad(xstar,viewer);
389:       VecAXPY(xstar, -1.0, x);
390:       VecNorm(xstar, NORM_2, &norm);
391:       PetscPrintf(PETSC_COMM_WORLD, "Error norm %g\n", (double)norm);
392:       VecDestroy(&xstar);
393:       PetscViewerDestroy(&viewer);
394:     }
395:     if (outputSoln) {
396:       PetscViewer viewer;

398:       PetscViewerBinaryOpen(PETSC_COMM_WORLD,"solution.petsc",FILE_MODE_WRITE,&viewer);
399:       VecView(x, viewer);
400:       PetscViewerDestroy(&viewer);
401:     }

403:     flg  = PETSC_FALSE;
404:     PetscOptionsGetBool(NULL, "-ksp_reason", &flg,NULL);
405:     if (flg) {
406:       KSPConvergedReason reason;
407:       KSPGetConvergedReason(ksp,&reason);
408:       PetscPrintf(PETSC_COMM_WORLD,"KSPConvergedReason: %D\n", reason);
409:     }

411:   }   /* while (num_numfac--) */

413:   /*
414:      Free work space.  All PETSc objects should be destroyed when they
415:      are no longer needed.
416:   */
417:   MatDestroy(&A); VecDestroy(&b);
418:   VecDestroy(&u); VecDestroy(&x);
419:   KSPDestroy(&ksp);
420:   PetscPreLoadEnd();
421:   /* -----------------------------------------------------------
422:                       End of linear solver loop
423:      ----------------------------------------------------------- */

425:   PetscFinalize();
426:   return 0;
427: }