Actual source code: itres.c
petsc-3.10.5 2019-03-28
2: #include <petsc/private/kspimpl.h>
4: /*@
5: KSPInitialResidual - Computes the residual. Either b - A*C*u = b - A*x with right
6: preconditioning or C*(b - A*x) with left preconditioning; that later
7: residual is often called the "preconditioned residual".
9: Collective on KSP
11: Input Parameters:
12: + vsoln - solution to use in computing residual
13: . vt1, vt2 - temporary work vectors
14: - vb - right-hand-side vector
16: Output Parameters:
17: . vres - calculated residual
19: Notes:
20: This routine assumes that an iterative method, designed for
21: $ A x = b
22: will be used with a preconditioner, C, such that the actual problem is either
23: $ AC u = b (right preconditioning) or
24: $ CA x = Cb (left preconditioning).
25: This means that the calculated residual will be scaled and/or preconditioned;
26: the true residual
27: $ b-Ax
28: is returned in the vt2 temporary.
30: Level: developer
32: .keywords: KSP, residual
34: .seealso: KSPMonitor()
35: @*/
37: PetscErrorCode KSPInitialResidual(KSP ksp,Vec vsoln,Vec vt1,Vec vt2,Vec vres,Vec vb)
38: {
39: Mat Amat,Pmat;
47: if (!ksp->pc) {KSPGetPC(ksp,&ksp->pc);}
48: PCGetOperators(ksp->pc,&Amat,&Pmat);
49: if (!ksp->guess_zero) {
50: /* skip right scaling since current guess already has it */
51: KSP_MatMult(ksp,Amat,vsoln,vt1);
52: VecCopy(vb,vt2);
53: VecAXPY(vt2,-1.0,vt1);
54: if (ksp->pc_side == PC_RIGHT) {
55: PCDiagonalScaleLeft(ksp->pc,vt2,vres);
56: } else if (ksp->pc_side == PC_LEFT) {
57: KSP_PCApply(ksp,vt2,vres);
58: PCDiagonalScaleLeft(ksp->pc,vres,vres);
59: } else if (ksp->pc_side == PC_SYMMETRIC) {
60: PCApplySymmetricLeft(ksp->pc,vt2,vres);
61: } else SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP, "Invalid preconditioning side %d", (int)ksp->pc_side);
62: } else {
63: VecCopy(vb,vt2);
64: if (ksp->pc_side == PC_RIGHT) {
65: PCDiagonalScaleLeft(ksp->pc,vb,vres);
66: } else if (ksp->pc_side == PC_LEFT) {
67: KSP_PCApply(ksp,vb,vres);
68: PCDiagonalScaleLeft(ksp->pc,vres,vres);
69: } else if (ksp->pc_side == PC_SYMMETRIC) {
70: PCApplySymmetricLeft(ksp->pc, vb, vres);
71: } else SETERRQ1(PetscObjectComm((PetscObject)ksp),PETSC_ERR_SUP, "Invalid preconditioning side %d", (int)ksp->pc_side);
72: }
73: return(0);
74: }
76: /*@
77: KSPUnwindPreconditioner - Unwinds the preconditioning in the solution. That is,
78: takes solution to the preconditioned problem and gets the solution to the
79: original problem from it.
81: Collective on KSP
83: Input Parameters:
84: + ksp - iterative context
85: . vsoln - solution vector
86: - vt1 - temporary work vector
88: Output Parameter:
89: . vsoln - contains solution on output
91: Notes:
92: If preconditioning either symmetrically or on the right, this routine solves
93: for the correction to the unpreconditioned problem. If preconditioning on
94: the left, nothing is done.
96: Level: advanced
98: .keywords: KSP, unwind, preconditioner
100: .seealso: KSPSetPCSide()
101: @*/
102: PetscErrorCode KSPUnwindPreconditioner(KSP ksp,Vec vsoln,Vec vt1)
103: {
109: if (!ksp->pc) {KSPGetPC(ksp,&ksp->pc);}
110: if (ksp->pc_side == PC_RIGHT) {
111: KSP_PCApply(ksp,vsoln,vt1);
112: PCDiagonalScaleRight(ksp->pc,vt1,vsoln);
113: } else if (ksp->pc_side == PC_SYMMETRIC) {
114: PCApplySymmetricRight(ksp->pc,vsoln,vt1);
115: VecCopy(vt1,vsoln);
116: } else {
117: PCDiagonalScaleRight(ksp->pc,vsoln,vsoln);
118: }
119: return(0);
120: }