Actual source code: ex10.c
petsc-dev 2014-02-02
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: }