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: }