> On Oct 6, 2020, at 6:57 AM, Olivier Jamond <[email protected]> wrote:
> 
> 
> On 03/10/2020 00:23, Barry Smith wrote:
>>    I think what Jed is saying is that you should just actually build your 
>> preconditioner for your Ct*C + Qt*S*Q operator with S. Because Ct is tall 
>> and skinny the eigenstructure of Ct*C + Qt*S*Q is just the eigenstructure of 
>> S with a low rank "modification" and Krylov methods (GMRES) are good at 
>> solving problems where the eigenstructure of the preconditioner is only a 
>> small rank modification of the eigenstructure of the operator you are supply 
>> to GMRES. In the best situation each new iteration of GMRES corrects one 
>> more of the "rogue" eigen directions. I would first use a direct solver with 
>> S just to test how well it works as a preconditioner and then switch to GAMG 
>> or whatever should work efficiently for solving your particular S matrix.
>> 
>>   I'd be interested in hearing how well the Ainsworth Formula works, it is 
>> something that might be worth adding to PCFIELDSPLIT.
>> 
>> 
>>   Barry
> 
> Hi Barry,
> 
> Thanks for these clarifications.
> 
> To give some context, the test I am working on is a traction on an 
> elastoplastic cube in large strain on which I apply 2% of strain at the first 
> loading increment. The cube has 14739 dofs, and the number of rows of the C 
> matrix is 867.
> 
> In this simple case, the C matrix just refers to simple dirichlet conditions. 
> Then Q is diagonal with 1. on dofs without dirichlet on 0. for dofs with 
> dirichlets. Q'*S*Q is like S with zeros on lines/columns referring to dofs 
> with dirichlet, and then C'*C just re-add non null value on the diagonal for 
> the dofs with dirichlet. In the end, I feel that in this case the ainsworth 
> method just do exactly the same as row/column elimination that can be done 
> with MatZeroRowsColumns and the x and b optional vectors provided.
> 
> On this test, with '-ksp_rtol 1.e-9' and '-ksp_type gmres', using S as a 
> preconditionning matrix and a direct solver gives 65 iterations of the gmres 
> for my first newton iteration (where S is SPD) and between 170 and 290 for 
> the next ones (S is still symmetric but has negative eigenvalues). If I use 
> '-pc_type gamg', the number of iterations of the gmres for the first (SPD) 
> newton iteration is (14 with Sp / 23 with S), and for the next ones (not SPD) 
> it is (~45 with Sp / ~180 with S).

   Given the structure of C it seems you should just explicitly construct Sp 
and use GAMG (or other preconditioners, even a direct solver) directly on Sp. 
Trying to avoid explicitly forming Sp will give you a much slower performing 
solving for what benefit? If C was just some generic monster than forming Sp 
might be unrealistic but in your case CCt is is block diagonal with tiny blocks 
which means (C*Ct)^(-1) is block diagonal with tiny blocks (the blocks are the 
inverses of the blocks of (C*Ct)).

    Sp = Ct*C  + Qt * S * Q = Ct*C  +  [I - Ct * (C*Ct)^(-1)*C] S [I - Ct * 
(C*Ct)^(-1)*C] 

[Ct * (C*Ct)^(-1)*C] will again be block diagonal with slightly larger blocks.

You can do D = (C*Ct) with MatMatMult() then write custom code that zips 
through the diagonal blocks of D inverting all of them to get iD then use 
MatPtAP applied to C and iD to get Ct * (C*Ct)^(-1)*C then MatShift() to 
include the I then MatPtAP or MatRAR to get [I - Ct * (C*Ct)^(-1)*C] S [I - Ct 
* (C*Ct)^(-1)*C]  then finally MatAXPY() to get Sp. The complexity of each of 
the Mat operations is very low because of the absurdly simple structure of C 
and its descendants.   You might even be able to just use MUMPS to give you the 
explicit inv(C*Ct) without writing custom code to get iD.

  Perhaps I am missing something? Note you can also prototype this process in 
Matlab very quickly to find any glitches. Hopefully you will find [I - Ct * 
(C*Ct)^(-1)*C] S [I - Ct * (C*Ct)^(-1)*C]  has only a slightly "bulked out" 
sparsity of S.



> 
> In this case with only simple dirichlets, I think I would like that the 
> PCApply does something like: (I-Q)*jacobi(Ct*C)*(I-Q) + Q*precond(S)*Q. BUt I 
> am not sure how to do that (I am quite newbie with petsc)... With a PCShell 
> and PCShellSetApply?

  I don't think there is any reason to think that using I-Q)*jacobi(Ct*C)*(I-Q) 
+ Q*precond(S)*Q.  would be a particularly good preconditioner for Sp. That is 
much better than using a preconditioner built from S.  But you can use 
PCCOMPOSITE and PCSHELL with KSP inside for the two jacobi(Ct*C) and precond(S).

Barry




> 
> In the end, if we found something that works well with the ainsworth formula, 
> it would be nice to have it natively with PCFIELDSPLIT!
> 
> Many thanks,
> Olivier
> 

Reply via email to