Actual source code: ex10.c

  1: /*$Id: ex10.c,v 1.58 2001/09/11 16:33:29 bsmith Exp $*/

  3: static char help[] = "Reads a PETSc matrix and vector from a file and solves a linear system.n
  4: This version first preloads and solves a small system, then loads n
  5: another (larger) system and solves it as well.  This example illustratesn
  6: preloading of instructions with the smaller system so that more accuraten
  7: performance monitoring can be done with the larger one (that actuallyn
  8: is the system of interest).  See the 'Performance Hints' chapter of then
  9: users manual for a discussion of preloading.  Input parameters includen
 10:   -f0 <input_file> : first file to load (small system)n
 11:   -f1 <input_file> : second file to load (larger system)nn
 12:   -trans  : solve transpose system insteadnn";
 13: /*
 14:   This code can be used to test PETSc interface to other packages.n
 15:   Examples of command line options: n
 16:    ex10 -f0 <datafile> -ksp_monitor n
 17:         -sles_view                  n
 18:         -num_numfac <num_numfac> -num_rhs <num_rhs> n
 19:         -pc_type lu -mat_aij_spooles/superlu/superlu_dist n
 20:         -pc_type cholesky -mat_baij_dscpack  -matload_type mpibaij n  
 21:         -pc_type cholesky -mat_sbaij_spooles -matload_type mpisbaijnn";
 22: */
 23: /*T
 24:    Concepts: SLES^solving a linear system
 25:    Processors: n
 26: T*/

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

 38:  #include src/vec/is/impls/general/general.h

 40: int main(int argc,char **args)
 41: {
 42:   SLES           sles;             /* linear solver context */
 43:   Mat            A;                /* matrix */
 44:   Vec            x,b,u;          /* approx solution, RHS, exact solution */
 45:   PetscViewer    fd;               /* viewer */
 46:   char           file[2][128];     /* input file name */
 47:   PetscTruth     table,flg,trans,partition = PETSC_FALSE;
 48:   int            ierr,its,ierrp;
 49:   PetscReal      norm;
 50:   PetscLogDouble tsetup,tsetup1,tsetup2,tsolve,tsolve1,tsolve2;
 51:   PetscScalar    zero = 0.0,none = -1.0;
 52:   PetscTruth     preload = PETSC_TRUE,diagonalscale;
 53:   int            num_numfac;

 55:   PetscInitialize(&argc,&args,(char *)0,help);

 57:   PetscOptionsHasName(PETSC_NULL,"-table",&table);
 58:   PetscOptionsHasName(PETSC_NULL,"-trans",&trans);
 59:   PetscOptionsHasName(PETSC_NULL,"-partition",&partition);

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

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

 89:     /* - - - - - - - - - - - New Stage - - - - - - - - - - - - -
 90:                            Load system
 91:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

 93:     /* 
 94:        Open binary file.  Note that we use PETSC_BINARY_RDONLY to indicate
 95:        reading from this file.
 96:     */
 97:     PetscViewerBinaryOpen(PETSC_COMM_WORLD,file[PreLoadIt],PETSC_BINARY_RDONLY,&fd);

 99:     /*
100:        Load the matrix and vector; then destroy the viewer.
101:     */
102:     ierr  = MatLoad(fd,MATMPIAIJ,&A);
103:     ierr  = PetscPushErrorHandler(PetscIgnoreErrorHandler,PETSC_NULL);
104:     ierrp = VecLoad(fd,&b);
105:     ierr  = PetscPopErrorHandler();
106:     if (ierrp) { /* if file contains no RHS, then use a vector of all ones */
107:       int    m;
108:       PetscScalar one = 1.0;
109:       MatGetLocalSize(A,&m,PETSC_NULL);
110:       VecCreate(PETSC_COMM_WORLD,&b);
111:       VecSetSizes(b,m,PETSC_DECIDE);
112:       VecSetFromOptions(b);
113:       VecSet(&one,b);
114:     }
115:     PetscViewerDestroy(fd);

117:     /* 
118:        If the loaded matrix is larger than the vector (due to being padded 
119:        to match the block size of the system), then create a new padded vector.
120:     */
121:     {
122:       int         m,n,j,mvec,start,end,index;
123:       Vec         tmp;
124:       PetscScalar *bold;

126:       /* Create a new vector b by padding the old one */
127:       MatGetLocalSize(A,&m,&n);
128:       VecCreate(PETSC_COMM_WORLD,&tmp);
129:       VecSetSizes(tmp,m,PETSC_DECIDE);
130:       VecSetFromOptions(tmp);
131:       VecGetOwnershipRange(b,&start,&end);
132:       VecGetLocalSize(b,&mvec);
133:       VecGetArray(b,&bold);
134:       for (j=0; j<mvec; j++) {
135:         index = start+j;
136:         ierr  = VecSetValues(tmp,1,&index,bold+j,INSERT_VALUES);
137:       }
138:       VecRestoreArray(b,&bold);
139:       VecDestroy(b);
140:       VecAssemblyBegin(tmp);
141:       VecAssemblyEnd(tmp);
142:       b = tmp;
143:     }
144:     VecDuplicate(b,&x);
145:     VecDuplicate(b,&u);
146:     VecSet(&zero,x);

148:     /* - - - - - - - - - - - New Stage - - - - - - - - - - - - -
149:                       Setup solve for system
150:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

152:     /*
153:        Conclude profiling last stage; begin profiling next stage.
154:     */
155:     PreLoadStage("SLESSetUp");

157:     if (partition) {
158:       MatPartitioning mpart;
159:       IS              mis,nis,isn,is;
160:       int             *count,size,rank;
161:       Mat             B;
162:       MPI_Comm_size(PETSC_COMM_WORLD,&size);
163:       MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
164:       PetscMalloc(size*sizeof(int),&count);
165:       MatPartitioningCreate(PETSC_COMM_WORLD, &mpart);
166:       MatPartitioningSetAdjacency(mpart, A);
167:       /* MatPartitioningSetVertexWeights(mpart, weight); */
168:       MatPartitioningSetFromOptions(mpart);
169:       MatPartitioningApply(mpart, &mis);
170:       MatPartitioningDestroy(mpart);
171:       ISPartitioningToNumbering(mis,&nis);
172:       ISPartitioningCount(mis,count);
173:       ISDestroy(mis);
174:       ISInvertPermutation(nis, count[rank], &is);
175:       PetscFree(count);
176:       ISDestroy(nis);
177:       ISSort(is);
178:       ISAllGather(is,&isn);
179:       MatGetSubMatrix(A,is,isn,PETSC_DECIDE,MAT_INITIAL_MATRIX,&B);

181:       /* need to move the vector also */
182:       ISDestroy(is);
183:       ISDestroy(isn);
184:       MatDestroy(A);
185:       A    = B;
186:     }
187: 
188:     /*
189:        We also explicitly time this stage via PetscGetTime()
190:     */
191:     PetscGetTime(&tsetup1);

193:     /*
194:        Create linear solver; set operators; set runtime options.
195:     */
196:     SLESCreate(PETSC_COMM_WORLD,&sles);

198:     num_numfac = 1;
199:     PetscOptionsGetInt(PETSC_NULL,"-num_numfac",&num_numfac,PETSC_NULL);
200:     while ( num_numfac-- ){
201:       /* SLESSetOperators(sles,A,A,DIFFERENT_NONZERO_PATTERN); */
202:     SLESSetOperators(sles,A,A,SAME_NONZERO_PATTERN);
203:     SLESSetFromOptions(sles);

205:     /* 
206:        Here we explicitly call SLESSetUp() and SLESSetUpOnBlocks() to
207:        enable more precise profiling of setting up the preconditioner.
208:        These calls are optional, since both will be called within
209:        SLESSolve() if they haven't been called already.
210:     */
211:     SLESSetUp(sles,b,x);
212:     SLESSetUpOnBlocks(sles);
213:     PetscGetTime(&tsetup2);
214:     tsetup = tsetup2 - tsetup1;

216:     /*
217:        Tests "diagonal-scaling of preconditioned residual norm" as used 
218:        by many ODE integrator codes including PVODE. Note this is different
219:        than diagonally scaling the matrix before computing the preconditioner
220:     */
221:     PetscOptionsHasName(PETSC_NULL,"-diagonal_scale",&diagonalscale);
222:     if (diagonalscale) {
223:       PC     pc;
224:       int    j,start,end,n;
225:       Vec    scale;
226: 
227:       SLESGetPC(sles,&pc);
228:       VecGetSize(x,&n);
229:       VecDuplicate(x,&scale);
230:       VecGetOwnershipRange(scale,&start,&end);
231:       for (j=start; j<end; j++) {
232:         VecSetValue(scale,j,((PetscReal)(j+1))/((PetscReal)n),INSERT_VALUES);
233:       }
234:       VecAssemblyBegin(scale);
235:       VecAssemblyEnd(scale);
236:       PCDiagonalScaleSet(pc,scale);
237:       VecDestroy(scale);

239:     }

241:     /* - - - - - - - - - - - New Stage - - - - - - - - - - - - -
242:                            Solve system
243:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

245:     /*
246:        Begin profiling next stage
247:     */
248:     PreLoadStage("SLESSolve");

250:     /*
251:        Solve linear system; we also explicitly time this stage.
252:     */
253:     PetscGetTime(&tsolve1);
254:     if (trans) {
255:       SLESSolveTranspose(sles,b,x,&its);
256:     } else {
257:       int  num_rhs=1;
258:       PetscOptionsGetInt(PETSC_NULL,"-num_rhs",&num_rhs,PETSC_NULL);
259:       while ( num_rhs-- ) {
260:         SLESSolve(sles,b,x,&its);
261:       }
262:     }
263:     PetscGetTime(&tsolve2);
264:     tsolve = tsolve2 - tsolve1;

266:    /* 
267:        Conclude profiling this stage
268:     */
269:     PreLoadStage("Cleanup");

271:     /* - - - - - - - - - - - New Stage - - - - - - - - - - - - -
272:             Check error, print output, free data structures.
273:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

275:     /* 
276:        Check error
277:     */
278:     if (trans) {
279:       MatMultTranspose(A,x,u);
280:     } else {
281:       MatMult(A,x,u);
282:     }
283:     VecAXPY(&none,b,u);
284:     VecNorm(u,NORM_2,&norm);

286:     /*
287:        Write output (optinally using table for solver details).
288:         - PetscPrintf() handles output for multiprocessor jobs 
289:           by printing from only one processor in the communicator.
290:         - SLESView() prints information about the linear solver.
291:     */
292:     if (table) {
293:       char        *matrixname,slesinfo[120];
294:       PetscViewer viewer;

296:       /*
297:          Open a string viewer; then write info to it.
298:       */
299:       PetscViewerStringOpen(PETSC_COMM_WORLD,slesinfo,120,&viewer);
300:       SLESView(sles,viewer);
301:       PetscStrrchr(file[PreLoadIt],'/',&matrixname);
302:       PetscPrintf(PETSC_COMM_WORLD,"%-8.8s %3d %2.0e %2.1e %2.1e %2.1e %s n",
303:                 matrixname,its,norm,tsetup+tsolve,tsetup,tsolve,slesinfo);

305:       /*
306:          Destroy the viewer
307:       */
308:       PetscViewerDestroy(viewer);
309:     } else {
310:       PetscPrintf(PETSC_COMM_WORLD,"Number of iterations = %3dn",its);
311:       PetscPrintf(PETSC_COMM_WORLD,"Residual norm %An",norm);
312:     }

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

316:     /* 
317:        Free work space.  All PETSc objects should be destroyed when they
318:        are no longer needed.
319:     */
320:     MatDestroy(A); VecDestroy(b);
321:     VecDestroy(u); VecDestroy(x);
322:     SLESDestroy(sles);
323:   PreLoadEnd();
324:   /* -----------------------------------------------------------
325:                       End of linear solver loop
326:      ----------------------------------------------------------- */

328:   PetscFinalize();
329:   return 0;
330: }