Actual source code: gsles.c

  1: #ifdef PETSC_RCS_HEADER
  2: static char vcid[] = "$Id: gsles.c,v 1.5 2000/01/10 03:54:18 knepley Exp $";
  3: #endif

 5:  #include petscsles.h
 6:  #include gsolver.h

  8: /*@
  9:   GVecSolutionKSPMonitor - Monitors solution at each KSP iteration.

 11:   Collective on KSP

 13:   Input Parameters:
 14: . ksp   - The Krylov subspace context
 15: . it    - The number of iterations so far
 16: . rnorm - The current (approximate) residual norm
 17: . ctx   - A viewer

 19:   Level: advanced

 21: .keywords: grid vector, ksp, monitor, solution
 22: .seealso: KSPDefaultMonitor(),KSPSetMonitor(),GVecResidualKSPMonitor(),
 23:           GVecRhsKSPMonitor(), GVecErrorKSPMonitor()
 24: @*/
 25: int GVecSolutionKSPMonitor(KSP ksp, int it, PetscReal rnorm, void *ctx)
 26: {
 27:   PetscViewer viewer = (PetscViewer) ctx;
 28:   Vec         x;
 29:   int         ierr;

 34:   KSPBuildSolution(ksp, PETSC_NULL, &x);
 35:   VecView(x, viewer);
 36:   return(0);
 37: }

 39: /*@
 40:   GVecResidualKSPMonitor - Monitors residual at each KSP iteration.

 42:   Collective on KSP

 44:   Input Parameters:
 45: . ksp   - The Krylov subspace context
 46: . it    - The number of iterations so far
 47: . rnorm - The current (approximate) residual norm
 48: . ctx   - A viewer

 50:   Level: advanced

 52: .keywords: grid vector, ksp, monitor, residual
 53: .seealso: KSPDefaultMonitor(),KSPSetMonitor(),GVecSolutionKSPMonitor(),
 54:           GVecRhsKSPMonitor(), GVecErrorKSPMonitor()
 55: @*/
 56: int GVecResidualKSPMonitor(KSP ksp, int it, PetscReal rnorm, void *ctx)
 57: {
 58:   PetscViewer viewer = (PetscViewer) ctx;
 59:   Vec         r;
 60:   int         ierr;

 65:   KSPBuildResidual(ksp, PETSC_NULL, PETSC_NULL, &r);
 66:   VecView(r, viewer);
 67:   return(0);
 68: }

 70: /*@
 71:   GVecRhsKSPMonitor - Displays the right hand side for the linear system at the first iteration.

 73:   Collective on KSP

 75:   Input Parameters:
 76: . ksp   - The Krylov subspace context
 77: . it    - The number of iterations so far
 78: . rnorm - The current (approximate) residual norm
 79: . ctx   - A viewer

 81:   Level: advanced

 83: .keywords: grid vector, ksp, monitor, rhs
 84: .seealso: KSPDefaultMonitor(),KSPSetMonitor(),GVecSolutionKSPMonitor(),
 85:           GVecResidualKSPMonitor(), GVecErrorKSPMonitor()
 86: @*/
 87: int GVecRhsKSPMonitor(KSP ksp, int it, PetscReal rnorm, void *ctx)
 88: {
 89:   PetscViewer viewer = (PetscViewer) ctx;
 90:   Vec         b;
 91:   int         ierr;

 96:   if (!it) {
 97:     KSPGetRhs(ksp, &b);
 98:     VecView(b, viewer);
 99:   }
100:   return(0);
101: }

103: /*@
104:   GVecErrorKSPMonitor - Displays the error at each iteration.

106:   Collective on KSP

108:   Input Parameters:
109: . ksp      - The Krylov subspace context
110: . it       - The number of iterations so far
111: . rnorm    - The current (approximate) residual norm
112: . errorCtx - A GVecErrorKSPMonitorCtx

114:   Notes: 
115:   The final argument to KSPSetMonitor() with this routine must be
116:   a pointer to a GVecErrorKSPMonitorCtx.

118:   Level: advanced

120: .keywords: grid vector, ksp, monitor, error
121: .seealso: KSPDefaultMonitor(),KSPSetMonitor(),,GVecSolutionKSPMonitor(),
122:           GVecResidualKSPMonitor(), GVecRhsKSPMonitor()
123: @*/
124: int GVecErrorKSPMonitor(KSP ksp, int it, PetscReal rnorm, void *errorCtx)
125: {
126:   GVecErrorKSPMonitorCtx *ctx  = (GVecErrorKSPMonitorCtx *) errorCtx;
127:   PetscScalar             mone = -1.0;
128:   GVec                    x, e;
129:   PetscReal               norm_2, norm_max;
130:   int                     ierr;

134:   KSPBuildSolution(ksp, PETSC_NULL, &x);
135:   GVecGetWorkGVec(ctx->solution, &e);
136:   VecWAXPY(&mone, x, ctx->solution, e);
137:   VecView(e, ctx->error_viewer);

139:   /* Compute 2-norm and max-norm of error */
140:   if (ctx->norm_error_viewer) {
141:     VecNorm(e, NORM_2, &norm_2);
142:     VecNorm(e, NORM_MAX, &norm_max);
143:     if (ctx->isInner == PETSC_FALSE) {
144:       PetscViewerASCIIPrintf(ctx->norm_error_viewer, "Iteration %d residual norm %g error 2-norm %g error max-norm %gn",
145:                              it, rnorm, norm_2, norm_max);
146:     } else {
147:       PetscViewerASCIIPrintf(ctx->norm_error_viewer, "  Inner iteration %d residual norm %g error 2-norm %g error max-norm %gn",
148:                              it, rnorm, norm_2, norm_max);
149:     }
150:   }

152:   GVecRestoreWorkGVec(ctx->solution, &e);
153:   return(0);
154: }

156:  #include petscmg.h
157: /* ------------------------------------------------------------------------------*/
158: /*
159:   GVecPCMGSetMonitor - Sets GVec KSP monitors for each level of multigrid.

161:    Input Parameters:
162: .    pc - preconditioner context for multigrid
163: */
164: int GVecPCMGSetMonitor(PC pc, int views)
165: {
166:   char         name[25];
167:   int          levels, i,ierr, solution,rhs,residual,all;
168:   SLES         subsles;
169:   KSP          ksp;
170:   PetscViewer *viewers;
171:   PetscTruth   match;

175:   PetscTypeCompare((PetscObject) pc, PCMG, &match);
176:   if (match == PETSC_FALSE) return(0);

178:   solution = (views & GVECPCMGMONITOR_SOLUTION);
179:   residual = (views & GVECPCMGMONITOR_RESIDUAL);
180:   rhs      = (views & GVECPCMGMONITOR_RHS);
181:   all      = (solution != 0) + (residual != 0) + (rhs != 0);

183:   MGGetLevels(pc, &levels);

185:   PetscMalloc(all*levels * sizeof(PetscViewer), &viewers);

187:   for(i = 0; i < levels; i++) {
188:     MGGetSmoother(pc, i, &subsles);
189:     SLESGetKSP(subsles, &ksp);
190:     if (rhs) {
191:       sprintf(name, "Right hand side %d",i);
192:       PetscViewerDrawOpen(PETSC_COMM_WORLD, 0, name, PETSC_DECIDE, PETSC_DECIDE, 200, 200, viewers);
193:       KSPSetMonitor(ksp, GVecRhsKSPMonitor, *viewers++, PETSC_NULL);
194:     }
195:     if (solution) {
196:       sprintf(name, "Solution %d",i);
197:       PetscViewerDrawOpen(PETSC_COMM_WORLD, 0, name, PETSC_DECIDE, PETSC_DECIDE, 200, 200, viewers);
198:       KSPSetMonitor(ksp, GVecSolutionKSPMonitor, *viewers++, PETSC_NULL);
199:     }
200:     if (residual) {
201:       sprintf(name, "Residual %d",i);
202:       PetscViewerDrawOpen(PETSC_COMM_WORLD, 0, name, PETSC_DECIDE, PETSC_DECIDE, 200, 200, viewers);
203:       KSPSetMonitor(ksp, GVecResidualKSPMonitor, *viewers++, PETSC_NULL);
204:     }
205:   }

207:   return(0);
208: }

210: EXTERN_C_BEGIN
211: int GVecKSPOptionsChecker_Private(KSP ksp)
212: {
213:   char       *prefix, string[64], *p;
214:   int         ierr, loc[4], nmax;
215:   MPI_Comm    comm;
216:   PetscViewer viewer;
217:   PetscDraw   draw;
218:   PetscTruth  opt;


223:   KSPGetOptionsPrefix(ksp, &prefix);
224:   PetscObjectGetComm((PetscObject) ksp, &comm);

226:   nmax = 4;
227:   loc[0] = PETSC_DECIDE; loc[1] = PETSC_DECIDE; loc[2] = 300; loc[3] = 300;
228:   PetscOptionsGetIntArray(prefix, "-gvec_ksp_solutionmonitor", loc, &nmax, &opt);
229:   if (opt) {
230:     PetscViewerDrawOpen(comm, 0, 0, loc[0], loc[1], loc[2], loc[3], &viewer);
231:     PetscViewerDrawGetDraw(viewer, 0, &draw);
232:     PetscDrawSetTitle(draw, "Approx. Solution");
233:     PetscLogObjectParent(ksp, (PetscObject) viewer);
234:     KSPSetMonitor(ksp, GVecSolutionKSPMonitor, (void *) viewer, PETSC_NULL);
235:   }
236:   nmax = 4;
237:   loc[0] = PETSC_DECIDE; loc[1] = PETSC_DECIDE; loc[2] = 300; loc[3] = 300;
238:   PetscOptionsGetIntArray(prefix, "-gvec_ksp_residualmonitor", loc, &nmax, &opt);
239:   if (opt) {
240:     PetscViewerDrawOpen(comm, 0, 0, loc[0], loc[1], loc[2], loc[3], &viewer);
241:     PetscViewerDrawGetDraw(viewer, 0, &draw);
242:     PetscDrawSetTitle(draw, "Residual");
243:     PetscLogObjectParent(ksp, (PetscObject) viewer);
244:     KSPSetMonitor(ksp, GVecResidualKSPMonitor, (void *) viewer, PETSC_NULL);
245:   }
246:   nmax = 4;
247:   loc[0] = PETSC_DECIDE; loc[1] = PETSC_DECIDE; loc[2] = 300; loc[3] = 300;
248:   PetscOptionsGetIntArray(prefix, "-gvec_ksp_rhsmonitor", loc, &nmax, &opt);
249:   if (opt) {
250:     PetscViewerDrawOpen(comm, 0, 0, loc[0], loc[1], loc[2], loc[3], &viewer);
251:     PetscViewerDrawGetDraw(viewer, 0, &draw);
252:     PetscDrawSetTitle(draw, "Rhs");
253:     PetscLogObjectParent(ksp, (PetscObject) viewer);
254:     KSPSetMonitor(ksp, GVecRhsKSPMonitor, (void *) viewer, PETSC_NULL);
255:   }
256:   PetscOptionsGetString(prefix, "-gvec_mg_monitor", string, 64, &opt);
257:   if (opt) {
258:     PC  pc;
259:     int all = 0;

261:     PetscStrstr(string, "nosolution", &p);
262:     if (!p) all |= GVECPCMGMONITOR_SOLUTION;
263:     PetscStrstr(string, "noresidual", &p);
264:     if (!p) all |= GVECPCMGMONITOR_RESIDUAL;
265:     PetscStrstr(string, "norhs",      &p);
266:     if (!p) all |= GVECPCMGMONITOR_RHS;
267:     KSPGetPC(ksp, &pc);
268:     GVecPCMGSetMonitor(pc, all);
269:   }
270:   PetscOptionsHasName(PETSC_NULL, "-help", &opt);
271:   if (opt) {
272:     char *pprefix;
273:     int   len = 2;

275:     if (prefix != PETSC_NULL) {
276:       PetscStrlen(prefix, &len);
277:     }
278:     PetscMalloc((len+2) * sizeof(char), &pprefix);
279:     PetscStrcpy(pprefix, "-");
280:     if (prefix != PETSC_NULL)
281:       PetscStrcat(pprefix, prefix);
282:     PetscPrintf(comm," Additional KSP Monitor options for grid vectorsn");
283:     PetscPrintf(comm,"   %sgvec_ksp_solutionmonitorn", pprefix);
284:     PetscPrintf(comm,"   %sgvec_ksp_residualmonitorn", pprefix);
285:     PetscPrintf(comm,"   %sgvec_ksp_rhsmonitorn", pprefix);
286:     PetscPrintf(comm,"   %sgvec_mg_monitor [nosolution,norhs,noresidual]n", pprefix);
287:     PetscFree(pprefix);
288:   }
289:   return(0);
290: }
291: EXTERN_C_END

293: /*--------------------------------------------------- Uzawa Methods --------------------------------------------------*/
294: /*@
295:    GMatCreateUzawa - Creates a container matrix for the Uzawa system matrix B^T A^{-1} B.

297:    Input Parameter:
298: +  A    - The square (0,0) block of the original saddle-point matrix
299: .  B    - The rectangular (0,1) block of the original saddle-point matrix
300: -  sles - The solver used to invert A

302:    Output Parameter:
303: .  gmat - The discrete operator

305:   Level: advanced

307: .seealso: GVecCreate()
308: @*/
309: int GMatCreateUzawa(GMat A, GMat B, SLES sles, GMat *gmat)
310: {
311:   UzawaContext *uCtx;
312:   MPI_Comm      comm;
313:   Grid          grid, grid2;
314:   int           M, m, N, n;
315:   int           O, o, P, p;
316:   int           ierr;

323:   GMatGetGrid(A, &grid);
324:   GMatGetGrid(B, &grid2);
327:   if (grid != grid2) SETERRQ(PETSC_ERR_ARG_INCOMP, "Matrices must all have the same underlying grid.");
328:   PetscNew(UzawaContext, &uCtx);
329:   uCtx->A    = A;
330:   uCtx->B    = B;
331:   uCtx->sles = sles;
332:   MatGetSize(A, &M, &N);
333:   MatGetLocalSize(A, &m, &n);
334:   MatGetSize(B, &O, &P);
335:   MatGetLocalSize(B, &o, &p);
336:   if ((m != o) || (n != o) || (M != O) || (N != O)) {
337:     SETERRQ(PETSC_ERR_ARG_INCOMP, "Incommensurate sizes, B^T A B must be a legal matrix");
338:   }
339:   PetscObjectGetComm((PetscObject) grid, &comm);
340:   MatCreateShell(comm, p, p, P, P, uCtx, gmat);
341:   MatShellSetOperation(*gmat, MATOP_MULT, (void (*)(void)) GMatMatMultUzawa);
342:   VecCreateMPI(comm, m, M, &uCtx->work);
343:   VecDuplicate(uCtx->work, &uCtx->work2);
344:   return(0);
345: }

347: /*@
348:   GMatMatMultUzawa - This function applies B^T A^{-1} B to a vector,
349:   which is the Schur complement matrix.

351:   Input Parameters:
352: + mat - The grid matrix
353: - x   - The input grid vector

355:   Output Parameter:
356: . y - The output grid vector B^T A^{-1} B x

358:   Level: advanced

360: .seealso: GMatEvaluateOperatorGalerkin
361: @*/
362: int GMatMatMultUzawa(GMat mat, GVec x, GVec y)
363: {
364:   UzawaContext *ctx;
365:   int           its;
366:   int           ierr;

372:   MatShellGetContext(mat, (void **) &ctx);
373:   MatMult(ctx->B, x, ctx->work);
374:   SLESSolve(ctx->sles, ctx->work, ctx->work2, &its);
375:   MatMultTranspose(ctx->B, ctx->work2, y);
376:   return(0);
377: }

379: /*@
380:    GMatDestroyUzawa - Destroys a container matrix for the Uzawa
381:    system matrix B^T A B.

383:    Input Parameter:
384: .  gmat - The container matrix from GMatCreateUzawa()

386:   Level: advanced

388: .seealso: GVecCreate()
389: @*/
390: int GMatDestroyUzawa(GMat gmat)
391: {
392:   UzawaContext *ctx;
393:   int           ierr;


398:   MatShellGetContext(gmat, (void **) &ctx);
399:   if (ctx != PETSC_NULL) {
400:     VecDestroy(ctx->work);
401:     VecDestroy(ctx->work2);
402:     PetscFree(ctx);
403:   }
404:   MatDestroy(gmat);
405:   return(0);
406: }