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