Actual source code: ex5.c
2: static char help[] = "Solves two linear systems in parallel with KSP. The code\n\
3: illustrates repeated solution of linear systems with the same preconditioner\n\
4: method but different matrices (having the same nonzero structure). The code\n\
5: also uses multiple profiling stages. Input arguments are\n\
6: -m <size> : problem size\n\
7: -mat_nonsym : use nonsymmetric matrix (default is symmetric)\n\n";
9: /*T
10: Concepts: KSP^repeatedly solving linear systems;
11: Concepts: PetscLog^profiling multiple stages of code;
12: Processors: n
13: T*/
15: /*
16: Include "petscksp.h" so that we can use KSP solvers. Note that this file
17: automatically includes:
18: petsc.h - base PETSc routines petscvec.h - vectors
19: petscsys.h - system routines petscmat.h - matrices
20: petscis.h - index sets petscksp.h - Krylov subspace methods
21: petscviewer.h - viewers petscpc.h - preconditioners
22: */
23: #include petscksp.h
27: int main(int argc,char **args)
28: {
29: KSP ksp; /* linear solver context */
30: Mat C; /* matrix */
31: Vec x,u,b; /* approx solution, RHS, exact solution */
32: PetscReal norm; /* norm of solution error */
33: PetscScalar v,none = -1.0;
34: PetscInt I,J,ldim,low,high,iglobal,Istart,Iend;
36: PetscInt i,j,m = 3,n = 2,its;
37: PetscMPIInt size,rank;
38: PetscTruth mat_nonsymmetric;
39: int stages[2];
41: PetscInitialize(&argc,&args,(char *)0,help);
42: PetscOptionsGetInt(PETSC_NULL,"-m",&m,PETSC_NULL);
43: MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
44: MPI_Comm_size(PETSC_COMM_WORLD,&size);
45: n = 2*size;
47: /*
48: Set flag if we are doing a nonsymmetric problem; the default is symmetric.
49: */
50: PetscOptionsHasName(PETSC_NULL,"-mat_nonsym",&mat_nonsymmetric);
52: /*
53: Register two stages for separate profiling of the two linear solves.
54: Use the runtime option -log_summary for a printout of performance
55: statistics at the program's conlusion.
56: */
57: PetscLogStageRegister(&stages[0],"Original Solve");
58: PetscLogStageRegister(&stages[1],"Second Solve");
60: /* -------------- Stage 0: Solve Original System ---------------------- */
61: /*
62: Indicate to PETSc profiling that we're beginning the first stage
63: */
64: PetscLogStagePush(stages[0]);
66: /*
67: Create parallel matrix, specifying only its global dimensions.
68: When using MatCreate(), the matrix format can be specified at
69: runtime. Also, the parallel partitioning of the matrix is
70: determined by PETSc at runtime.
71: */
72: MatCreate(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,m*n,m*n,&C);
73: MatSetFromOptions(C);
75: /*
76: Currently, all PETSc parallel matrix formats are partitioned by
77: contiguous chunks of rows across the processors. Determine which
78: rows of the matrix are locally owned.
79: */
80: MatGetOwnershipRange(C,&Istart,&Iend);
82: /*
83: Set matrix entries matrix in parallel.
84: - Each processor needs to insert only elements that it owns
85: locally (but any non-local elements will be sent to the
86: appropriate processor during matrix assembly).
87: - Always specify global row and columns of matrix entries.
88: */
89: for (I=Istart; I<Iend; I++) {
90: v = -1.0; i = I/n; j = I - i*n;
91: if (i>0) {J = I - n; MatSetValues(C,1,&I,1,&J,&v,ADD_VALUES);}
92: if (i<m-1) {J = I + n; MatSetValues(C,1,&I,1,&J,&v,ADD_VALUES);}
93: if (j>0) {J = I - 1; MatSetValues(C,1,&I,1,&J,&v,ADD_VALUES);}
94: if (j<n-1) {J = I + 1; MatSetValues(C,1,&I,1,&J,&v,ADD_VALUES);}
95: v = 4.0; MatSetValues(C,1,&I,1,&I,&v,ADD_VALUES);
96: }
98: /*
99: Make the matrix nonsymmetric if desired
100: */
101: if (mat_nonsymmetric) {
102: for (I=Istart; I<Iend; I++) {
103: v = -1.5; i = I/n;
104: if (i>1) {J = I-n-1; MatSetValues(C,1,&I,1,&J,&v,ADD_VALUES);}
105: }
106: } else {
107: MatSetOption(C,MAT_SYMMETRIC);
108: MatSetOption(C,MAT_SYMMETRY_ETERNAL);
109: }
111: /*
112: Assemble matrix, using the 2-step process:
113: MatAssemblyBegin(), MatAssemblyEnd()
114: Computations can be done while messages are in transition
115: by placing code between these two statements.
116: */
117: MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);
118: MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);
120: /*
121: Create parallel vectors.
122: - When using VecSetSizes(), we specify only the vector's global
123: dimension; the parallel partitioning is determined at runtime.
124: - Note: We form 1 vector from scratch and then duplicate as needed.
125: */
126: VecCreate(PETSC_COMM_WORLD,&u);
127: VecSetSizes(u,PETSC_DECIDE,m*n);
128: VecSetFromOptions(u);
129: VecDuplicate(u,&b);
130: VecDuplicate(b,&x);
132: /*
133: Currently, all parallel PETSc vectors are partitioned by
134: contiguous chunks across the processors. Determine which
135: range of entries are locally owned.
136: */
137: VecGetOwnershipRange(x,&low,&high);
139: /*
140: Set elements within the exact solution vector in parallel.
141: - Each processor needs to insert only elements that it owns
142: locally (but any non-local entries will be sent to the
143: appropriate processor during vector assembly).
144: - Always specify global locations of vector entries.
145: */
146: VecGetLocalSize(x,&ldim);
147: for (i=0; i<ldim; i++) {
148: iglobal = i + low;
149: v = (PetscScalar)(i + 100*rank);
150: VecSetValues(u,1,&iglobal,&v,INSERT_VALUES);
151: }
153: /*
154: Assemble vector, using the 2-step process:
155: VecAssemblyBegin(), VecAssemblyEnd()
156: Computations can be done while messages are in transition,
157: by placing code between these two statements.
158: */
159: VecAssemblyBegin(u);
160: VecAssemblyEnd(u);
162: /*
163: Compute right-hand-side vector
164: */
165: MatMult(C,u,b);
166:
167: /*
168: Create linear solver context
169: */
170: KSPCreate(PETSC_COMM_WORLD,&ksp);
172: /*
173: Set operators. Here the matrix that defines the linear system
174: also serves as the preconditioning matrix.
175: */
176: KSPSetOperators(ksp,C,C,DIFFERENT_NONZERO_PATTERN);
178: /*
179: Set runtime options (e.g., -ksp_type <type> -pc_type <type>)
180: */
182: KSPSetFromOptions(ksp);
184: /*
185: Solve linear system. Here we explicitly call KSPSetUp() for more
186: detailed performance monitoring of certain preconditioners, such
187: as ICC and ILU. This call is optional, as KSPSetUp() will
188: automatically be called within KSPSolve() if it hasn't been
189: called already.
190: */
191: KSPSetUp(ksp);
192: KSPSolve(ksp,b,x);
193:
194: /*
195: Check the error
196: */
197: VecAXPY(&none,u,x);
198: VecNorm(x,NORM_2,&norm);
199: KSPGetIterationNumber(ksp,&its);
200: PetscPrintf(PETSC_COMM_WORLD,"Norm of error %A, Iterations %D\n",norm,its);
202: /* -------------- Stage 1: Solve Second System ---------------------- */
203: /*
204: Solve another linear system with the same method. We reuse the KSP
205: context, matrix and vector data structures, and hence save the
206: overhead of creating new ones.
208: Indicate to PETSc profiling that we're concluding the first
209: stage with PetscLogStagePop(), and beginning the second stage with
210: PetscLogStagePush().
211: */
212: PetscLogStagePop();
213: PetscLogStagePush(stages[1]);
215: /*
216: Initialize all matrix entries to zero. MatZeroEntries() retains the
217: nonzero structure of the matrix for sparse formats.
218: */
219: MatZeroEntries(C);
221: /*
222: Assemble matrix again. Note that we retain the same matrix data
223: structure and the same nonzero pattern; we just change the values
224: of the matrix entries.
225: */
226: for (i=0; i<m; i++) {
227: for (j=2*rank; j<2*rank+2; j++) {
228: v = -1.0; I = j + n*i;
229: if (i>0) {J = I - n; MatSetValues(C,1,&I,1,&J,&v,ADD_VALUES);}
230: if (i<m-1) {J = I + n; MatSetValues(C,1,&I,1,&J,&v,ADD_VALUES);}
231: if (j>0) {J = I - 1; MatSetValues(C,1,&I,1,&J,&v,ADD_VALUES);}
232: if (j<n-1) {J = I + 1; MatSetValues(C,1,&I,1,&J,&v,ADD_VALUES);}
233: v = 6.0; MatSetValues(C,1,&I,1,&I,&v,ADD_VALUES);
234: }
235: }
236: if (mat_nonsymmetric) {
237: for (I=Istart; I<Iend; I++) {
238: v = -1.5; i = I/n;
239: if (i>1) {J = I-n-1; MatSetValues(C,1,&I,1,&J,&v,ADD_VALUES);}
240: }
241: }
242: MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);
243: MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);
245: /*
246: Compute another right-hand-side vector
247: */
248: MatMult(C,u,b);
250: /*
251: Set operators. Here the matrix that defines the linear system
252: also serves as the preconditioning matrix.
253: - The flag SAME_NONZERO_PATTERN indicates that the
254: preconditioning matrix has identical nonzero structure
255: as during the last linear solve (although the values of
256: the entries have changed). Thus, we can save some
257: work in setting up the preconditioner (e.g., no need to
258: redo symbolic factorization for ILU/ICC preconditioners).
259: - If the nonzero structure of the matrix is different during
260: the second linear solve, then the flag DIFFERENT_NONZERO_PATTERN
261: must be used instead. If you are unsure whether the
262: matrix structure has changed or not, use the flag
263: DIFFERENT_NONZERO_PATTERN.
264: - Caution: If you specify SAME_NONZERO_PATTERN, PETSc
265: believes your assertion and does not check the structure
266: of the matrix. If you erroneously claim that the structure
267: is the same when it actually is not, the new preconditioner
268: will not function correctly. Thus, use this optimization
269: feature with caution!
270: */
271: KSPSetOperators(ksp,C,C,SAME_NONZERO_PATTERN);
273: /*
274: Solve linear system
275: */
276: KSPSetUp(ksp);
277: KSPSolve(ksp,b,x);
279: /*
280: Check the error
281: */
282: VecAXPY(&none,u,x);
283: VecNorm(x,NORM_2,&norm);
284: KSPGetIterationNumber(ksp,&its);
285: PetscPrintf(PETSC_COMM_WORLD,"Norm of error %A, Iterations %D\n",norm,its);
287: /*
288: Free work space. All PETSc objects should be destroyed when they
289: are no longer needed.
290: */
291: KSPDestroy(ksp);
292: VecDestroy(u);
293: VecDestroy(x);
294: VecDestroy(b);
295: MatDestroy(C);
297: /*
298: Indicate to PETSc profiling that we're concluding the second stage
299: */
300: PetscLogStagePop();
302: PetscFinalize();
303: return 0;
304: }