[petsc-users] V-cycle multigrid with matrix shells

Sylvain Barbot sylbar.vainbot at gmail.com
Thu May 12 01:01:40 CDT 2011


Hi Barry,

I have tested the direct solver with the shell matrix and it works
very well. In my code, the matrix-multiply operation is implemented
with the function "matrixantiplanefv". I am now trying to do it with
multi-grid. I am keeping a direct solver solely for the coarse-level.
I will do this coarse solve matrix-free with the function
"matrixantiplanecoarsefv". I am also setting up all the other
operations (residual, smoother, restriction, interpolation) with
matrix-free methods. The setup is done in the subroutine
"green_init_mg".

First I set up a PCMG preconditionner:

CALL KSPCreate(PETSC_COMM_WORLD,c%ksp,ierr);
CALL KSPGetPC(c%ksp,c%pc,ierr);
CALL PCSetType(c%pc,PCMG,ierr);
CALL PCMGSetLevels(c%pc,c%nlevels,PETSC_NULL_OBJECT,ierr);
CALL PCMGSetType(c%pc,PC_MG_MULTIPLICATIVE,ierr);
CALL PCMGSetCycleType(c%pc,PC_MG_CYCLE_V,ierr);
CALL PCMGSetNumberSmoothUp(c%pc,1,ierr);
CALL PCMGSetNumberSmoothDown(c%pc,1,ierr);


Then I set up the coarse solver:

CALL MatCreateShell(PETSC_COMM_WORLD, &

cinfo%zm*cinfo%ym*cinfo%xm*info%dof,cinfo%zm*cinfo%ym*cinfo%xm*cinfo%dof,
&

cinfo%mz*cinfo%my*cinfo%mx*info%dof,cinfo%mz*cinfo%my*cinfo%mx*cinfo%dof,
&
                        PETSC_NULL,c%cA,ierr);
CALL MatShellSetOperation(c%cA,MATOP_MULT,matrixantiplanecoarsefv,ierr);
CALL MatAssemblyBegin(c%cA,MAT_FINAL_ASSEMBLY,ierr);
CALL MatAssemblyEnd(c%cA,MAT_FINAL_ASSEMBLY,ierr);
CALL KSPSetOperators(c%cksp,c%cA,c%cA,DIFFERENT_NONZERO_PATTERN,ierr);
CALL KSPSetUp(c%cksp,ierr);
CALL PCMGGetCoarseSolve(c%pc,c%cksp,ierr);


Then I set up the interpolation and restriction:

DO l=1,c%nlevels-1
       ...
       ! shell matrix MxN with M>N
       CALL MatCreateShell(PETSC_COMM_WORLD, &

cinfo%zm*cinfo%ym*cinfo%xm*cinfo%dof,minfo%zm*minfo%ym*minfo%xm*minfo%dof,
&

cinfo%mz*cinfo%my*cinfo%mx*cinfo%dof,minfo%mz*minfo%my*minfo%mx*minfo%dof,
&
                           PETSC_NULL,c%interp(l),ierr);

       CALL MatShellSetOperation(c%interp(l),MATOP_MULT,matrixinterp,ierr);
       CALL MatAssemblyBegin(c%interp(l),MAT_FINAL_ASSEMBLY,ierr);
       CALL MatAssemblyEnd(c%interp(l),MAT_FINAL_ASSEMBLY,ierr);

       ! shell matrix MxN with M<N
       CALL MatCreateShell(PETSC_COMM_WORLD, &

minfo%zm*minfo%ym*minfo%xm*minfo%dof,cinfo%zm*cinfo%ym*cinfo%xm*cinfo%dof,
&

minfo%mz*minfo%my*minfo%mx*minfo%dof,cinfo%mz*cinfo%my*cinfo%mx*cinfo%dof,
&
                           PETSC_NULL,c%restrict(l),ierr);

       CALL MatShellSetOperation(c%restrict(l),MATOP_MULT,matrixrestrict,ierr);
       CALL MatAssemblyBegin(c%restrict(l),MAT_FINAL_ASSEMBLY,ierr);
       CALL MatAssemblyEnd(c%restrict(l),MAT_FINAL_ASSEMBLY,ierr);

       ! define the intergrid transfer operations
       CALL PCMGSetInterpolation(c%pc,l,c%interp(l),ierr);
       CALL PCMGSetRestriction(c%pc,l,c%restrict(l),ierr);

END DO

Then i provide the smoother for each level:

DO l=0,c%nlevels-1
       ! global size at current level
       cinfo%mx=(info%mx/2**(c%nlevels-l))*2+1
       cinfo%my=(info%my/2**(c%nlevels-l))*2+1
       cinfo%mz=1
       ! locally-owned size at current level
       CALL getmxl(x,info%xm,c%nlevels-l-1,cinfo%xm)
       CALL getmxl(y,info%ym,c%nlevels-l-1,cinfo%ym)
       cinfo%zm=1
       cinfo%dof=info%dof

       !-----------------------------------------------------------------------------
       ! smoothing matrix
       !-----------------------------------------------------------------------------

       ! square smoothing matrix
       CALL MatCreateShell(PETSC_COMM_WORLD, &

cinfo%zm*cinfo%ym*cinfo%xm*cinfo%dof,cinfo%zm*cinfo%ym*cinfo%xm*cinfo%dof,
&

cinfo%mz*cinfo%my*cinfo%mx*cinfo%dof,cinfo%mz*cinfo%my*cinfo%mx*cinfo%dof,
&
                           PETSC_NULL,c%sA(l+1),ierr);

       CALL MatShellSetOperation(c%sA(l+1),MATOP_MULT,matrixsmoothfv,ierr);
       CALL MatAssemblyBegin(c%sA(l+1),MAT_FINAL_ASSEMBLY,ierr);
       CALL MatAssemblyEnd(c%sA(l+1),MAT_FINAL_ASSEMBLY,ierr);

       CALL PCMGGetSmoother(c%pc,l,sksp,ierr);
       CALL KSPCreate(PETSC_COMM_WORLD,sksp,ierr);
       CALL KSPSetOperators(sksp,c%sA(l+1),c%sA(l+1),DIFFERENT_NONZERO_PATTERN,ierr);
       CALL KSPSetUp(sksp,ierr);

       !-----------------------------------------------------------------------------
       ! residual operator
       !-----------------------------------------------------------------------------

       ! square forward-model matrix
       CALL MatCreateShell(PETSC_COMM_WORLD, &

cinfo%zm*cinfo%ym*cinfo%xm*cinfo%dof,cinfo%zm*cinfo%ym*cinfo%xm*cinfo%dof,
&

cinfo%mz*cinfo%my*cinfo%mx*cinfo%dof,cinfo%mz*cinfo%my*cinfo%mx*cinfo%dof,
&
                           PETSC_NULL,c%rA(l+1),ierr);

       CALL MatShellSetOperation(c%rA(l+1),MATOP_MULT,matrixresidualfv,ierr);
       CALL MatAssemblyBegin(c%rA(l+1),MAT_FINAL_ASSEMBLY,ierr);
       CALL MatAssemblyEnd(c%rA(l+1),MAT_FINAL_ASSEMBLY,ierr);

       ! compute formula b - Ax with matrix-free matrix
       CALL PCMGSetResidual(c%pc,l,matrixresidualfv,c%rA(l+1),ierr);

END DO

I also provide work space...
Despite that, I have a crash upon running KSPSetup() with "[0]PETSC
ERROR: PCSetUp_BJacobi()".


Also, I do no wish to provide a shell matrix for a direct solver at
the finest level but if I don't I get the error:

MatGetVecs() line 7265 in src/mat/interface/matrix.c
[0]PETSC ERROR: KSPGetVecs() line 806 in src/ksp/ksp/interface/iterativ.c
[0]PETSC ERROR: KSPSetUp_GMRES() line 94 in src/ksp/ksp/impls/gmres/gmres.c
[0]PETSC ERROR: KSPSetUp() line

So despite all my efforts, it looks that the solver still attempts to
do a direct solve.

I would appreciate your comments.
Best wishes,
Sylvain

2011/5/10 Barry Smith <bsmith at mcs.anl.gov>:
>
>
>   Barry
>
>
> On May 10, 2011, at 9:20 PM, Sylvain Barbot wrote:
>
>> Dear Jed,
>>
>> Thank you for your previous comments. I am still trying to design a
>> multigrid preconditionner for the Navier's equation of elasticity. I
>> have defined shell matrices for the interpolation, restriction,
>> smoothing, residual calculation and the fine-level solver (see
>> attached my_green.f90 file with stub functions). I thought that all
>> these shell matrices would be enough to do the job, but upon running
>> KSPSetup(), I get the following error:
>>
>> [0]PETSC ERROR: No support for this operation for this object type!
>> [0]PETSC ERROR: This matrix type, shell, does not support getting
>> diagonal block!
>> [0]PETSC ERROR:
>> ------------------------------------------------------------------------
>> [0]PETSC ERROR: Petsc Release Version 3.1.0, Patch 4, Fri Jul 30
>> 14:42:02 CDT 2010
>> [0]PETSC ERROR:
>> ------------------------------------------------------------------------
>> [0]PETSC ERROR: PCSetUp_BJacobi() line 162 in src/ksp/pc/impls/bjacobi/bjacobi.c
>> [0]PETSC ERROR: PCSetUp() line 795 in src/ksp/pc/interface/precon.c
>> [0]PETSC ERROR: KSPSetUp() line 237 in src/ksp/ksp/interface/itfunc.c
>> [0]PETSC ERROR: PCSetUp_MG() line 574 in src/ksp/pc/impls/mg/mg.c
>>
>> regarding your previous comments: "For Jacobi, you can have your
>> MatShell implement MatGetDiagonal and it will work. (...) If you want
>> to use a multiplicative relaxation like SOR, you would have to
>> implement it yourself.", I actually want to use SOR with my smoother
>> shell matrix. What am I doing wrong to make petsc still believe I want
>> to use Jacobi?
>>
>
>  By default, it is using block Jacobi on each level (except the coarsest). You need to tell it to use the relaxation you have coded. For example if your shell matrix provides a SOR/relaxation method then you need to use -mg_levels_pc_type sor  and it will call that on each level instead of block Jacobi. In looking at your code I see the only operation your provide your shell matrices are matrix-vector multiply. Therefore you cannot use SOR/relaxation. The only think you can use is GMRES (or some other Krylov method) with no preconditioner as the smoother. For this you can use -mg_levels_pc_type none -mg_levels_ksp_type gmres
>
>   In your message  you say  "I actually want to use SOR with my smoother" to do this you need to provide the smoother function and set it with MatShellSetOperations().
>
>
>> another related question: with a direct solver, one needs to assign a
>> shell matrix with a KSP object (KSPSetOperators); is it still required
>> when using multigrid? if I don't do so, I get the following error:
>>
>  Where are you using the direct solver for, on the entire linear system or on the coarse mesh? In either case you NEED to provide an explicit (not shell) sparse matrix otherwise a direct solver cannot be used. From the message below it looks like you did not provide a matrix somewhere. If you don't provide a matrix a direct solver cannot be used.
>
>
>   Barry
>
>> [0]PETSC ERROR: Null argument, when expecting valid pointer!
>> [0]PETSC ERROR: Null Object: Parameter # 1!
>> [0]PETSC ERROR: MatGetVecs() line 7265 in src/mat/interface/matrix.c
>> [0]PETSC ERROR: KSPGetVecs() line 806 in src/ksp/ksp/interface/iterativ.c
>> [0]PETSC ERROR: KSPSetUp_GMRES() line 94 in src/ksp/ksp/impls/gmres/gmres.c
>> [0]PETSC ERROR: KSPSetUp() line 199 in src/ksp/ksp/interface/itfunc.c
>>
>> however, I don't understand why I would need this matrix in a
>> multigrid framework.
>>
>> Is there any example out there of using PCMG with shell matrices?
>>
>> Thanks in advance for your response.
>> Best wishes,
>> Sylvain Barbot
>>
>>
>> 2010/10/7 Jed Brown <jed at 59a2.org>:
>>> On Thu, Oct 7, 2010 at 11:45, Sylvain Barbot <sylbar.vainbot at gmail.com>
>>> wrote:
>>>>
>>>> questions:
>>>> 1) is it at all possible to specify this mode of operation, from the
>>>> finest to the coarser level, and back? Any examples out there?
>>>
>>> -pc_mg_type multiplicative, or
>>>   PCMGSetType(pc,PC_MG_MULTIPLICATIVE);
>>>
>>>>
>>>> 2) is it readily possible to use matrix shells with DMMG? I imagine
>>>> the Jacobian matrix may simply be provided as a matrix shell. Is there
>>>> any examples of multi-grid methods with shell matrices online?
>>>
>>> You can do this, but you will have to define a custom smoother.  For Jacobi,
>>> you can have your MatShell implement MatGetDiagonal and it will work.  I
>>> thought you could implement MatGetDiagonalBlock for PBJacobi, but it's not
>>> currently written that way (though it should be and that would be an easy
>>> change to make).  If you want to use a multiplicative relaxation like SOR,
>>> you would have to implement it yourself.  If you need something like ILU for
>>> a smoother, then you will have to pay for a matrix.  Note that one
>>> possibility is to assemble a matrix on all but the finest level so you can
>>> use stronger smoothers there, then make do with Jacobi on the finest level.
>>>
>>>>
>>>> 3) to deal with non-uniform sampling: can I provide the coordinates of
>>>> the finest grid with DASetCoordinates, then expect DMMG to provide the
>>>> subsampled coordinates at the coarser levels?
>>>
>>> Currently no, you have to set them on each level.  Perhaps you could do this
>>> by rolling a loop over levels and applying MatRestrict using the restriction
>>> matrix from DMMG (this might not be the sampling that you want).
>>> Jed
>> <my_green.f90>
>
>


More information about the petsc-users mailing list