<html aria-label="message body"><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><div>  The preconditioner is always built from the second of the two matrices passed in KSPSetOperators() or PCSetOperators(). In the first case below both matrices are the same (the nest matrix) and so diagonal is extracted from the nest matrix (which is the only matrix). In the second case below the first matrix is custom and the second is the next matrix, again the preconditioner is constructed from the second one. </div><div><br></div><div><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">      linear system matrix = precond matrix:</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">      Mat Object: 1 MPI process</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        type: nest</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        rows=524, cols=524</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">          Matrix object:</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        type=nest, rows=3, cols=3</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        MatNest structure:</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        (0,0) : type=mpiaij, rows=176, cols=176</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        (0,1) : NULL</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        (0,2) : NULL</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        (1,0) : NULL</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        (1,1) : type=mpiaij, rows=172, cols=172</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        (1,2) : NULL</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        (2,0) : NULL</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        (2,1) : NULL</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        (2,2) : type=mpiaij, rows=176, cols=176</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        </span></div><div><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">Mat Object: 1 MPI process</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">      type: python</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        Python: __main__.LHSOperator</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">    Mat Object: 1 MPI process</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">      type: nest</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">      Matrix object:</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        type=nest, rows=3, cols=3</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        MatNest structure:</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        (0,0) : type=mpiaij, rows=176, cols=176</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        (0,1) : NULL</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        (0,2) : NULL</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        (1,0) : NULL</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        (1,1) : type=mpiaij, rows=172, cols=172</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        (1,2) : NULL</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        (2,0) : NULL</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        (2,1) : NULL</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        (2,2) : type=mpiaij, rows=176, cols=176</span><br style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">        </span></div><div><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><br></span></div><div><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">The arguments to KSPSetOperators() and PCSetOperators() are stored in the same place (inside the PC) </span></div><div><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><br></span></div><div><span style="font-family: Calibri, Helvetica, sans-serif; font-size: 16px;">In fact,</span></div><div><span style="font-family: Calibri, Helvetica, sans-serif; font-size: 16px;"><br></span></div><div><div>PetscErrorCode KSPSetOperators(KSP ksp, Mat Amat, Mat Pmat)</div><div>{</div><div> ....</div><div>  PetscCall(PCSetOperators(ksp->pc, Amat, Pmat));</div></div><div><br></div><div><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><br></span></div><div><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><br></span></div><div><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">so when you call</span></div><div><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><br></span></div><div><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">   precond.setOperators(A=nest_mass_matrix, P=None)</span></div><div><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">   ksp.setPC(precond)</span></div><div><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;"><br></span></div><div><span style="font-size: 16px; font-family: Calibri, Helvetica, sans-serif;">you are overwriting the A = </span><font face="Calibri, Helvetica, sans-serif" size="3">lhs that you passed into </font><span style="font-family: Calibri, Helvetica, sans-serif; font-size: 16px;"> </span><span style="font-family: Calibri, Helvetica, sans-serif; font-size: 16px;">ksp.setOperators(ksp, lhs, None).</span></div><div><span style="font-family: Calibri, Helvetica, sans-serif; font-size: 16px;"><br></span></div><div><span style="font-family: Calibri, Helvetica, sans-serif; font-size: 16px;">Given the names  ksp.setOperators() and precond.setOperators() I can see how this can be confusing. It is reasonable to conclude that ksp.setOperators is providing the linear system and that pc.setOperators() is providing the matrix with which to build the preconditioner, but that is not the case. </span></div><div><span style="font-family: Calibri, Helvetica, sans-serif; font-size: 16px;"><br></span></div><div><span style="font-family: Calibri, Helvetica, sans-serif; font-size: 16px;">But the code has been this way for 31 years. I am not sure what we can change with the documentation. Perhaps in KSPSetOperators it can say that it sets them into the PC.</span></div><div><span style="font-family: Calibri, Helvetica, sans-serif; font-size: 16px;"><br></span></div><div><span style="font-family: Calibri, Helvetica, sans-serif; font-size: 16px;">Barry</span></div><div><span style="font-family: Calibri, Helvetica, sans-serif; font-size: 16px;"><br></span></div><div><span style="font-family: Calibri, Helvetica, sans-serif; font-size: 16px;"><br></span></div><div><br></div><div><div><br><blockquote type="cite"><div>On Nov 4, 2025, at 4:06 AM, Moral Sanchez, Elena <Elena.Moral.Sanchez@ipp.mpg.de> wrote:</div><br class="Apple-interchange-newline"><div><meta charset="UTF-8"><div id="divtagdefaultwrapper" dir="ltr" style="font-style: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none; font-size: 12pt; font-family: Calibri, Helvetica, sans-serif;"><p style="margin-top: 0px; margin-bottom: 0px;"></p><div><div style="margin-top: 0px; margin-bottom: 0px;">Dear Barry,</div><div style="margin-top: 0px; margin-bottom: 0px;">Thanks for the fast answer. Unfortunately in my case the discrepancy is huge. With the flags</div><blockquote><div style="margin-top: 0px; margin-bottom: 0px;"> -ksp_monitor_true_residual -ksp_norm_type unpreconditioned</div></blockquote><div style="margin-top: 0px; margin-bottom: 0px;">this is the output:</div><blockquote><div style="margin-top: 0px; margin-bottom: 0px;">  0 KSP unpreconditioned resid norm 5.568889644229e-01 true resid norm 5.568889644229e-01 ||r(i)||/||b|| 1.000000000000e+00<br>  1 KSP unpreconditioned resid norm 2.831772665189e-01 true resid norm 2.831772665189e-01 ||r(i)||/||b|| 5.084986139245e-01<br>  2 KSP unpreconditioned resid norm 1.875950094147e-01 true resid norm 1.875950094147e-01 ||r(i)||/||b|| 3.368625011435e-01</div></blockquote><div style="margin-top: 0px; margin-bottom: 0px;">and this is the output of my own monitor function:</div><blockquote><div style="margin-top: 0px; margin-bottom: 0px;">Iter 0/10 | res = 5.57e-01/1.00e-08 | 0.0 s<br>difference KSPBuildSolution and u: 0.0<br>UNPRECONDITIONED norm:  0.5568889644229376<br>PRECONDITIONED norm:  2.049041078011257<br>KSPBuildResidual 2-norm: 0.5568889644229299<br>difference KSPBuildResidual and b-A(KSPBuildSolution): 6.573603152700697e-13<br><br>Iter 1/10 | res = 2.83e-01/1.00e-08 | 0.0 s<br>difference KSPBuildSolution and u: 0.0<br>UNPRECONDITIONED norm:  0.7661983589104541<br>PRECONDITIONED norm:  2.7387602134717137<br>KSPBuildResidual 2-norm: 0.2831772665189212<br>difference KSPBuildResidual and b-A(KSPBuildSolution): 0.1700718741085172<br><br>Iter 2/10 | res = 1.88e-01/1.00e-08 | 0.0 s<br>difference KSPBuildSolution and u: 0.0<br>UNPRECONDITIONED norm:  0.7050518160900253<br>PRECONDITIONED norm:  2.421773833445645<br>KSPBuildResidual 2-norm: 0.18759500941469456<br>difference KSPBuildResidual and b-A(KSPBuildSolution): 0.19327058976599623</div></blockquote><div style="margin-top: 0px; margin-bottom: 0px;">Here u is the vector in the KSPSolve. </div><div style="margin-top: 0px; margin-bottom: 0px;">After the first iteration, the residual computed from KSPBuildSolution and the residual from KSPBuildResidual diverge. They are the same when I run the same code without preconditioner.</div><div style="margin-top: 0px; margin-bottom: 0px;">Another observation is that after convergence (wrt. unpreconditioned norm == 2-norm of KSPBuildResidual) the solution with and without preconditioner looks quite different. How is this possible if my preconditioner is SPD?</div><div style="margin-top: 0px; margin-bottom: 0px;"><br></div><div style="margin-top: 0px; margin-bottom: 0px;">By the way, where can I find your implementation of "My monitor" in src/snes/tutorials/ex5.c? I tried to look at the Gitlab repository but could not find it.</div><div style="margin-top: 0px; margin-bottom: 0px;">Thanks for the help.</div><div style="margin-top: 0px; margin-bottom: 0px;">Cheers,</div><div style="margin-top: 0px; margin-bottom: 0px;">Elena</div></div><p style="margin-top: 0px; margin-bottom: 0px;"></p><div style="margin-top: 0px; margin-bottom: 0px;"><br></div><div style="margin-top: 0px; margin-bottom: 0px;"><br></div><div style="margin-top: 0px; margin-bottom: 0px;"><br></div><div style="margin-top: 0px; margin-bottom: 0px;"><br></div><div style="margin-top: 0px; margin-bottom: 0px;"><br></div><div class="moz-cite-prefix">On 11/4/25 03:01, Barry Smith wrote:<br></div><blockquote type="cite"><div>    0 KSP unpreconditioned resid norm 1.265943996096e+00 true resid norm 1.265943996096e+00 ||r(i)||/||b|| 1.000000000000e+00</div><div>My monitor 0 1.265943996096e+00</div></blockquote></div></div></blockquote></div><br></div></body></html>