<div dir="ltr"><div><div><div>Hi Barry,<br><br></div>Thanks so much for this work. I will checkout your branch, and take a look.<br><br></div>Thanks again!<br><br></div>Fande Kong,<br><div><div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Oct 13, 2016 at 8:10 PM, Barry Smith <span dir="ltr"><<a href="mailto:bsmith@mcs.anl.gov" target="_blank">bsmith@mcs.anl.gov</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
  Fande,<br>
<br>
   I have done some work, mostly understanding and documentation, on handling singular systems with KSP in the branch barry/improve-matnullspace-<wbr>usage. This also includes a new example that solves both a symmetric example and an example where nullspace(A) != nullspace(A') src/ksp/ksp/examples/<wbr>tutorials/ex67.c<br>
<br>
   My understanding is now documented in the manual page for KSPSolve(), part of this is quoted below:<br>
<br>
-------<br>
   If you provide a matrix that has a MatSetNullSpace() and MatSetTransposeNullSpace() this will use that information to solve singular systems<br>
   in the least squares sense with a norm minimizing solution.<br>
$<br>
$                   A x = b   where b = b_p + b_t where b_t is not in the range of A (and hence by the fundamental theorem of linear algebra is in the nullspace(A') see MatSetNullSpace()<br>
$<br>
$    KSP first removes b_t producing the linear system  A x = b_p (which has multiple solutions) and solves this to find the ||x|| minimizing solution (and hence<br>
$    it finds the solution x orthogonal to the nullspace(A). The algorithm is simply in each iteration of the Krylov method we remove the nullspace(A) from the search<br>
$    direction thus the solution which is a linear combination of the search directions has no component in the nullspace(A).<br>
$<br>
$    We recommend always using GMRES for such singular systems.<br>
$    If nullspace(A) = nullspace(A') (note symmetric matrices always satisfy this property) then both left and right preconditioning will work<br>
$    If nullspace(A) != nullspace(A') then left preconditioning will work but right preconditioning may not work (or it may).<br>
<br>
   Developer Note: The reason we cannot always solve  nullspace(A) != nullspace(A') systems with right preconditioning is because we need to remove at each iteration<br>
       the nullspace(AB) from the search direction. While we know the nullspace(A) the nullspace(AB) equals B^-1 times the nullspace(A) but except for trivial preconditioners<br>
       such as diagonal scaling we cannot apply the inverse of the preconditioner to a vector and thus cannot compute the nullspace(AB).<br>
------<br>
<br>
Any feed back on the correctness or clarity of the material is appreciated. The punch line is that right preconditioning cannot be trusted with nullspace(A) != nullspace(A') I don't see any fix for this.<br>
<span class="HOEnZb"><font color="#888888"><br>
  Barry<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
<br>
<br>
> On Oct 11, 2016, at 3:04 PM, Kong, Fande <<a href="mailto:fande.kong@inl.gov">fande.kong@inl.gov</a>> wrote:<br>
><br>
><br>
><br>
> On Tue, Oct 11, 2016 at 12:18 PM, Barry Smith <<a href="mailto:bsmith@mcs.anl.gov">bsmith@mcs.anl.gov</a>> wrote:<br>
><br>
> > On Oct 11, 2016, at 12:01 PM, Kong, Fande <<a href="mailto:fande.kong@inl.gov">fande.kong@inl.gov</a>> wrote:<br>
> ><br>
> ><br>
> ><br>
> > On Tue, Oct 11, 2016 at 10:39 AM, Barry Smith <<a href="mailto:bsmith@mcs.anl.gov">bsmith@mcs.anl.gov</a>> wrote:<br>
> ><br>
> > > On Oct 11, 2016, at 9:33 AM, Kong, Fande <<a href="mailto:fande.kong@inl.gov">fande.kong@inl.gov</a>> wrote:<br>
> > ><br>
> > > Barry, Thanks so much for your explanation. It helps me a lot.<br>
> > ><br>
> > > On Mon, Oct 10, 2016 at 4:00 PM, Barry Smith <<a href="mailto:bsmith@mcs.anl.gov">bsmith@mcs.anl.gov</a>> wrote:<br>
> > ><br>
> > > > On Oct 10, 2016, at 4:01 PM, Kong, Fande <<a href="mailto:fande.kong@inl.gov">fande.kong@inl.gov</a>> wrote:<br>
> > > ><br>
> > > > Hi All,<br>
> > > ><br>
> > > > I know how to remove the null spaces from a singular system using creating a MatNullSpace and attaching it to Mat.<br>
> > > ><br>
> > > > I was really wondering what is the philosophy behind this? The exact algorithms we are using in PETSc right now?  Where we are dealing with this, preconditioner, linear solver, or nonlinear solver?<br>
> > ><br>
> > >    It is in the Krylov solver.<br>
> > ><br>
> > >    The idea is very simple. Say you have   a singular A with null space N (that all values Ny are in the null space of A. So N is tall and skinny) and you want to solve A x = b where b is in the range of A. This problem has an infinite number of solutions     Ny + x*  since A (Ny + x*) = ANy + Ax* = Ax* = b where x* is the "minimum norm solution; that is Ax* = b and x* has the smallest norm of all solutions.<br>
> > ><br>
> > >       With left preconditioning   B A x = B b GMRES, for example, normally computes the solution in the as alpha_1 Bb   + alpha_2 BABb + alpha_3 BABABAb + ....  but the B operator will likely introduce some component into the direction of the null space so as GMRES continues the "solution" computed will grow larger and larger with a large component in the null space of A. Hence we simply modify GMRES a tiny bit by building the solution from alpha_1 (I-N)Bb   + alpha_2 (I-N)BABb + alpha_3<br>
> > ><br>
> > >  Does "I" mean an identity matrix? Could you possibly send me a link for this GMRES implementation, that is, how PETSc does this in the actual code?<br>
> ><br>
> >    Yes.<br>
> ><br>
> >     It is in the helper routine KSP_PCApplyBAorAB()<br>
> > #undef __FUNCT__<br>
> > #define __FUNCT__ "KSP_PCApplyBAorAB"<br>
> > PETSC_STATIC_INLINE PetscErrorCode KSP_PCApplyBAorAB(KSP ksp,Vec x,Vec y,Vec w)<br>
> > {<br>
> >   PetscErrorCode ierr;<br>
> >   PetscFunctionBegin;<br>
> >   if (!ksp->transpose_solve) {<br>
> >     ierr = PCApplyBAorAB(ksp->pc,ksp->pc_<wbr>side,x,y,w);CHKERRQ(ierr);<br>
> >     ierr = KSP_RemoveNullSpace(ksp,y);<wbr>CHKERRQ(ierr);<br>
> >   } else {<br>
> >     ierr = PCApplyBAorABTranspose(ksp-><wbr>pc,ksp->pc_side,x,y,w);<wbr>CHKERRQ(ierr);<br>
> >   }<br>
> >   PetscFunctionReturn(0);<br>
> > }<br>
> ><br>
> ><br>
> > PETSC_STATIC_INLINE PetscErrorCode KSP_RemoveNullSpace(KSP ksp,Vec y)<br>
> > {<br>
> >   PetscErrorCode ierr;<br>
> >   PetscFunctionBegin;<br>
> >   if (ksp->pc_side == PC_LEFT) {<br>
> >     Mat          A;<br>
> >     MatNullSpace nullsp;<br>
> >     ierr = PCGetOperators(ksp->pc,&A,<wbr>NULL);CHKERRQ(ierr);<br>
> >     ierr = MatGetNullSpace(A,&nullsp);<wbr>CHKERRQ(ierr);<br>
> >     if (nullsp) {<br>
> >       ierr = MatNullSpaceRemove(nullsp,y);<wbr>CHKERRQ(ierr);<br>
> >     }<br>
> >   }<br>
> >   PetscFunctionReturn(0);<br>
> > }<br>
> ><br>
> > "ksp->pc_side == PC_LEFT" deals with the left preconditioning Krylov methods only? How about the right preconditioning ones? Are  they just magically right for the right preconditioning Krylov methods?<br>
><br>
>    This is a good question. I am working on a branch now where I will add some more comprehensive testing of the various cases and fix anything that comes up.<br>
><br>
>    Were you having trouble with ASM and bjacobi only for right preconditioning?<br>
><br>
><br>
> Yes. ASM and bjacobi works fine for left preconditioning NOT for RIGHT preconditioning. bjacobi converges, but produces a wrong solution. ASM needs more iterations, however the solution is right.<br>
><br>
><br>
><br>
>     Note that when A is symmetric the range of A is orthogonal to null space of A so yes I think in that case it is just "magically right" but if A is not symmetric then I don't think it is "magically right". I'll work on it.<br>
><br>
><br>
>    Barry<br>
><br>
> ><br>
> > Fande Kong,<br>
> ><br>
> ><br>
> > There is no code directly in the GMRES or other methods.<br>
> ><br>
> > ><br>
> > > (I-N)BABABAb + ....  that is we remove from each new direction anything in the direction of the null space. Hence the null space doesn't directly appear in the preconditioner, just in the KSP method.   If you attach a null space to the matrix, the KSP just automatically uses it to do the removal above.<br>
> > ><br>
> > >     With right preconditioning the solution is built from alpha_1 b   + alpha_2 ABb + alpha_3 ABABb + .... and again we apply (I-N) to each term to remove any part that is in the null space of A.<br>
> > ><br>
> > >    Now consider the case   A y = b where b is NOT in the range of A. So the problem has no "true" solution, but one can find a least squares solution by rewriting b = b_par + b_perp where b_par is in the range of A and b_perp is orthogonal to the range of A and solve instead    A x = b_perp. If you provide a MatSetTransposeNullSpace() then KSP automatically uses it to remove b_perp from the right hand side before starting the KSP iterations.<br>
> > ><br>
> > >   The manual pages for MatNullSpaceAttach() and MatTranposeNullSpaceAttach() discuss this an explain how it relates to the fundamental theorem of linear algebra.<br>
> > ><br>
> > >   Note that for symmetric matrices the two null spaces are the same.<br>
> > ><br>
> > >   Barry<br>
> > ><br>
> > ><br>
> > >    A different note: This "trick" is not a "cure all" for a totally inappropriate preconditioner. For example if one uses for a preconditioner a direct (sparse or dense) solver or an ILU(k) one can end up with a very bad solver because the direct solver will likely produce a very small pivot at some point thus the triangular solver applied in the precondition can produce HUGE changes in the solution (that are not physical) and so the preconditioner basically produces garbage. On the other hand sometimes it works out ok.<br>
> > ><br>
> > > What preconditioners  are appropriate? asm, bjacobi, amg? I have an example which shows  lu and ilu indeed work, but asm and bjacobi do not at all. That is why I am asking questions about algorithms. I am trying to figure out a default preconditioner for several singular systems.<br>
> ><br>
> >    Hmm, normally asm and bjacobi would be fine with this unless one or more of the subblocks are themselves singular (which normally won't happen). AMG can also work find sometimes.<br>
> ><br>
> >    Can you send a sample code?<br>
> ><br>
> >   Barry<br>
> ><br>
> > ><br>
> > > Thanks again.<br>
> > ><br>
> > ><br>
> > > Fande Kong,<br>
> > ><br>
> > ><br>
> > ><br>
> > > ><br>
> > > ><br>
> > > > Fande Kong,<br>
><br>
><br>
<br>
</div></div></blockquote></div><br></div></div></div></div></div></div>