The following assumes you are not using the shell matrix context for some other purpose
> subroutine formJacobian(snes,F_global,Jac,Jac_pre,dummy,err_PETSc) > > SNES :: snes > Vec :: F_global > > ! real(pREAL), dimension(3,3,cells(1),cells(2),cells3), intent(in) :: & > ! F > Mat :: Jac, Jac_pre > PetscObject :: dummy > PetscErrorCode :: err_PETSc > > print*, '@@ start build my jac' > > PetscCall(MatShellSetContext(Jac,F_global,ierr)) ! record the current > base vector where the Jacobian is to be applied > print*, '@@ end build my jac' > > end subroutine formJacobian subroutine Gk_op ... Vec base PetscCall(MatShellGetContext(Jac,base,ierr)) ! use base in the computation of your matrix-free Jacobian vector product .... > On Jan 11, 2024, at 5:55 AM, Yi Hu <y...@mpie.de> wrote: > > Now I understand a bit more about the workflow of set jacobian. It seems that > the SNES can be really fine-grained. As you point out, J is built via > formJacobian() callback, and can be based on previous solution (or the base > vector u, as you mentioned). And then KSP can use a customized MATOP_MULT to > solve the linear equations J(u)*x=rhs. > > So I followed your idea about removing DMSNESSetJacobianLocal() and did the > following. > > …… > call MatCreateShell(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,& > > 9*product(cells(1:2))*cells3,9*product(cells(1:2))*cells3,& > 0,Jac_PETSc,err_PETSc) > CHKERRQ(err_PETSc) > call MatShellSetOperation(Jac_PETSc,MATOP_MULT,GK_op,err_PETSc) > CHKERRQ(err_PETSc) > call SNESSetJacobian(SNES_mech,Jac_PETSc,Jac_PETSc,formJacobian,0,err_PETSc) > CHKERRQ(err_PETSc) > …… > > And my formJacobian() is > > subroutine formJacobian(snes,F_global,Jac,Jac_pre,dummy,err_PETSc) > > SNES :: snes > Vec :: F_global > > ! real(pREAL), dimension(3,3,cells(1),cells(2),cells3), intent(in) :: & > ! F > Mat :: Jac, Jac_pre > PetscObject :: dummy > PetscErrorCode :: err_PETSc > > print*, '@@ start build my jac' > > call MatCopy(Jac_PETSc,Jac,SAME_NONZERO_PATTERN,err_PETSc) > CHKERRQ(err_PETSc) > call MatCopy(Jac_PETSc,Jac_pre,SAME_NONZERO_PATTERN,err_PETSc) > CHKERRQ(err_PETSc) > ! Jac = Jac_PETSc > ! Jac_pre = Jac_PETSc > > print*, '@@ end build my jac' > > end subroutine formJacobian > > it turns out that no matter by a simple assignment or MatCopy(), the compiled > program gives me the same error as before. So I guess the real jacobian is > still not set. I wonder how to get around this and let this built jac in > formJacobian() to be the same as my shell matrix. > > Yi > > From: Barry Smith <bsm...@petsc.dev <mailto:bsm...@petsc.dev>> > Sent: Wednesday, January 10, 2024 4:27 PM > To: Yi Hu <y...@mpie.de <mailto:y...@mpie.de>> > Cc: petsc-users <petsc-users@mcs.anl.gov <mailto:petsc-users@mcs.anl.gov>> > Subject: Re: [petsc-users] SNES seems not use my matrix-free operation > > > By default if SNESSetJacobian() is not called with a function pointer PETSc > attempts to compute the Jacobian matrix explicitly with finite differences > and coloring. This doesn't makes sense with a shell matrix. Hence the error > message below regarding MatFDColoringCreate(). > > DMSNESSetJacobianLocal() calls SNESSetJacobian() with a function pointer of > SNESComputeJacobian_DMLocal() so preventing the error from triggering in your > code. > > You can provide your own function to SNESSetJacobian() and thus not need to > call DMSNESSetJacobianLocal(). What you do depends on how you want to record > the "base" vector that tells your matrix-free multiply routine where the > Jacobian matrix vector product is being applied, that is J(u)*x. u is the > "base" vector which is passed to the function provided with SNESSetJacobian(). > > Barry > > > > On Jan 10, 2024, at 6:20 AM, Yi Hu <y...@mpie.de <mailto:y...@mpie.de>> wrote: > > Thanks for the clarification. It is more clear to me now about the global to > local processes after checking the examples, e.g. > ksp/ksp/tutorials/ex14f.F90. > > And for using Vec locally, I followed your advice of VecGet.. and VecRestore… > In fact I used DMDAVecGetArrayReadF90() and some other relevant subroutines. > > For your comment on DMSNESSetJacobianLocal(). It seems that I need to use > both SNESSetJacobian() and then DMSNESSetJacobianLocal() to get things > working. When I do only SNESSetJacobian(), it does not work, meaning the > following does not work > > …… > call > DMDASNESsetFunctionLocal(DM_mech,INSERT_VALUES,formResidual,PETSC_NULL_SNES,err_PETSc) > > CHKERRQ(err_PETSc) > call MatCreateShell(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,& > > 9*product(cells(1:2))*cells3,9*product(cells(1:2))*cells3,& > 0,Jac_PETSc,err_PETSc) > CHKERRQ(err_PETSc) > call MatShellSetOperation(Jac_PETSc,MATOP_MULT,GK_op,err_PETSc) > CHKERRQ(err_PETSc) > call > SNESSetJacobian(SNES_mech,Jac_PETSc,Jac_PETSc,PETSC_NULL_FUNCTION,0,err_PETSc) > CHKERRQ(err_PETSc) > !call DMSNESsetJacobianLocal(DM_mech,formJacobian,PETSC_NULL_SNES,err_PETSc) > !CHKERRQ(err_PETSc) > call > SNESsetConvergenceTest(SNES_mech,converged,PETSC_NULL_SNES,PETSC_NULL_FUNCTION,err_PETSc) > > CHKERRQ(err_PETSc) > call SNESSetDM(SNES_mech,DM_mech,err_PETSc) > CHKERRQ(err_PETSc) > …… > > It gives me the message > [0]PETSC ERROR: No support for this operation for this object type > > [0]PETSC ERROR: Code not yet written for matrix type shell > > [0]PETSC ERROR: See https://petsc.org/release/faq/ for trouble shooting. > > [0]PETSC ERROR: Petsc Release Version 3.16.4, Feb 02, 2022 > [0]PETSC ERROR: Configure options PETSC_ARCH=linux-gnu > --with-fortran-bindings --with-mpi-f90module-visibility=0 --download-fftw > --download-hdf5 --download-hdf5-fortran-bindings --download-fblaslapack > --download-ml --download-zlib > > [0]PETSC ERROR: #1 MatFDColoringCreate() at > /home/yi/app/petsc-3.16.4/src/mat/matfd/fdmatrix.c:471 > [0]PETSC ERROR: #2 SNESComputeJacobian_DMDA() at > /home/yi/app/petsc-3.16.4/src/snes/utils/dmdasnes.c:173[0]PETSC ERROR: #3 > SNESComputeJacobian() at > /home/yi/app/petsc-3.16.4/src/snes/interface/snes.c:2864 > [0]PETSC ERROR: #4 SNESSolve_NEWTONLS() at > /home/yi/app/petsc-3.16.4/src/snes/impls/ls/ls.c:222 > [0]PETSC ERROR: #5 SNESSolve() at > /home/yi/app/petsc-3.16.4/src/snes/interface/snes.c:4809 > [0]PETSC ERROR: #6 User provided function() at User file:0 > > [0]PETSC ERROR: #7 VecSetErrorIfLocked() at > /home/yi/app/petsc-3.16.4/include/petscvec.h:623 > [0]PETSC ERROR: #8 VecGetArray() at > /home/yi/app/petsc-3.16.4/src/vec/vec/interface/rvector.c:1769 > [0]PETSC ERROR: #9 User provided function() at User file:0 > > [0]PETSC ERROR: #10 MatFDColoringCreate() at > /home/yi/app/petsc-3.16.4/src/mat/matfd/fdmatrix.c:471 > [0]PETSC ERROR: #11 SNESComputeJacobian_DMDA() at > /home/yi/app/petsc-3.16.4/src/snes/utils/dmdasnes.c:173 > > > [0]PETSC ERROR: #12 SNESComputeJacobian() at > /home/yi/app/petsc-3.16.4/src/snes/interface/snes.c:2864 > [0]PETSC ERROR: #13 SNESSolve_NEWTONLS() at > /home/yi/app/petsc-3.16.4/src/snes/impls/ls/ls.c:222 > [0]PETSC ERROR: #14 SNESSolve() at > /home/yi/app/petsc-3.16.4/src/snes/interface/snes.c:4809 > > It seems that I have to use a DMSNESSetJacobianLocal() to “activate” the use > of my shell matrix, although the formJacobian() in the > DMSNESSetJacobianLocal() is doing nothing. > > Best wishes, > Yi > > > > From: Barry Smith <bsm...@petsc.dev <mailto:bsm...@petsc.dev>> > Sent: Tuesday, January 9, 2024 4:49 PM > To: Yi Hu <y...@mpie.de <mailto:y...@mpie.de>> > Cc: petsc-users <petsc-users@mcs.anl.gov <mailto:petsc-users@mcs.anl.gov>> > Subject: Re: [petsc-users] SNES seems not use my matrix-free operation > > However, my GK_op (which is the reloaded MATOP_MULT) gives me some problem. > It is entered but then crashed with Segmentation Violation error. So I guess > my indices may be wrong. I wonder do I need to use the local Vec (of dF), and > should my output Vec also be in the correct shape (i.e. after calculation I > need to transform back into a Vec)? As you can see here, my dF is a tensor > defined on every grid point. > > > The input for the matrix-vector product is a global vector, as is the > result. (Not like the arguments to DMSNESSetJacobianLocal). > > This means that your MATOP_MULT function needs to do the > DMGlobalToLocal() vector operation first then the "unwrapping" from the > vector to the array format at the beginning of the routine. Similarly it > needs to "unwrap" the result vector as an array. See > src/snes/tutorials/ex14f.F90 and in particular the code block > > PetscCall(DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX,ierr)) > PetscCall(DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX,ierr)) > > ! Get pointers to vector data > > PetscCall(VecGetArrayReadF90(localX,xx,ierr)) > PetscCall(VecGetArrayF90(F,ff,ierr)) > > Barry > > You really shouldn't be using DMSNESSetJacobianLocal() for your code. > Basically all the DMSNESSetJacobianLocal() gives you is that it automatically > handles the global to local mapping and unwrapping of the vector to an array, > but it doesn't work for shell matrices. > > > > > On Jan 9, 2024, at 6:30 AM, Yi Hu <y...@mpie.de <mailto:y...@mpie.de>> wrote: > > Dear Barry, > > Thanks for your help. > > It works when doing first SNESSetJacobian() with my created shell matrix Jac > in the main (or module) and then DMSNESSetJacobianLocal() to associate with > my DM and an dummy formJacobian callback (which is doing nothing). My SNES > can now recognize my shell matrix and do my customized operation. > > However, my GK_op (which is the reloaded MATOP_MULT) gives me some problem. > It is entered but then crashed with Segmentation Violation error. So I guess > my indices may be wrong. I wonder do I need to use the local Vec (of dF), and > should my output Vec also be in the correct shape (i.e. after calculation I > need to transform back into a Vec)? As you can see here, my dF is a tensor > defined on every grid point. > > Best wishes, > Yi > > From: Barry Smith <bsm...@petsc.dev <mailto:bsm...@petsc.dev>> > Sent: Monday, January 8, 2024 6:41 PM > To: Yi Hu <y...@mpie.de <mailto:y...@mpie.de>> > Cc: petsc-users@mcs.anl.gov <mailto:petsc-users@mcs.anl.gov> > Subject: Re: [petsc-users] SNES seems not use my matrix-free operation > > > "formJacobian" should not be __creating__ the matrices. Here "form" means > computing the numerical values in the matrix (or when using a shell matrix it > means keeping a copy of X so that your custom matrix-free multiply knows the > base location where the matrix free Jacobian-vector products are computed.) > > You create the shell matrices up in your main program and pass them in > with SNESSetJacobian(). > > Try first calling SNESSetJacobian() to provide the matrices (provide a > dummy function argument) and then call DMSNESSetJacobianLocal() to provide > your "formjacobian" function (that does not create the matrices). > > Barry > > > Yes, "form" is a bad word that should not have been used in our code. > > > > > > > On Jan 8, 2024, at 12:24 PM, Yi Hu <y...@mpie.de <mailto:y...@mpie.de>> wrote: > > Dear PETSc Experts, > > I am implementing a matrix-free jacobian for my SNES solver in Fortran. > (command line option -snes_type newtonls -ksp_type gmres) > > In the main program, I define my residual and jacobian and matrix-free > jacobian like the following, > > … > call DMDASNESSetFunctionLocal(DM_mech, INSERT_VALUES, formResidual, > PETSC_NULL_SNES, err_PETSc) > call DMSNESSetJacobianLocal(DM_mech, formJacobian, PETSC_NULL_SNES, err_PETSc) > … > > subroutine formJacobian(residual_subdomain,F,Jac_pre,Jac,dummy,err_PETSc) > > #include <petsc/finclude/petscmat.h> > use petscmat > implicit None > DMDALocalInfo, dimension(DMDA_LOCAL_INFO_SIZE) :: & > residual_subdomain > !< DMDA info (needs to be named "in" for macros like > XRANGE to work) > real(pREAL), dimension(3,3,cells(1),cells(2),cells3), intent(in) :: & > F > !< deformation gradient field > Mat :: Jac, Jac_pre > PetscObject :: dummy > PetscErrorCode :: err_PETSc > PetscInt :: N_dof ! global number of DoF, maybe > only a placeholder > > N_dof = 9*product(cells(1:2))*cells3 > > print*, 'in my jac' > > call > MatCreateShell(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,N_dof,N_dof,0,Jac,err_PETSc) > CHKERRQ(err_PETSc) > call MatShellSetOperation(Jac,MATOP_MULT,GK_op,err_PETSc) > CHKERRQ(err_PETSc) > > print*, 'in my jac' > > ! for jac preconditioner > call > MatCreateShell(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,N_dof,N_dof,0,Jac_pre,err_PETSc) > CHKERRQ(err_PETSc) > call MatShellSetOperation(Jac_pre,MATOP_MULT,GK_op,err_PETSc) > CHKERRQ(err_PETSc) > > print*, 'in my jac' > > end subroutine formJacobian > > subroutine GK_op(Jac,dF,output,err_PETSc) > real(pREAL), dimension(3,3,cells(1),cells(2),cells3), intent(in) :: & > dF > > real(pREAL), dimension(3,3,cells(1),cells(2),cells3), intent(out) :: & > output > > real(pREAL), dimension(3,3) :: & > deltaF_aim = 0.0_pREAL > > Mat :: Jac > PetscErrorCode :: err_PETSc > > integer :: i, j, k, e > > … a lot of calculations … > > print*, 'in GK op' > > end subroutine GK_op > > The first question is that: it seems I still need to explicitly define the > interface of MatCreateShell() and MatShellSetOperation() to properly use > them, even though I include them via “use petscmat”. It is a little bit > strange to me, since some examples do not perform this step. > > Then the main issue is that I can build my own Jacobian from my call back > function formJacobian, and confirm my Jacobian is a shell matrix (by > MatView). However, my customized operator GK_op is not called when solving > the nonlinear system (not print my “in GK op”). When I try to monitor my > SNES, it gives me some conventional output not mentioning my matrix-free > operations. So I guess my customized MATOP_MULT may be not associated with > Jacobian. Or my configuration is somehow wrong. Could you help me solve this > issue? > > Thanks, > Yi > > > > > > ------------------------------------------------- > Stay up to date and follow us on LinkedIn, Twitter and YouTube. > > Max-Planck-Institut für Eisenforschung GmbH > Max-Planck-Straße 1 > D-40237 Düsseldorf > > Handelsregister B 2533 > Amtsgericht Düsseldorf > > Geschäftsführung > Prof. Dr. Gerhard Dehm > Prof. Dr. Jörg Neugebauer > Prof. Dr. Dierk Raabe > Dr. Kai de Weldige > > Ust.-Id.-Nr.: DE 11 93 58 514 > Steuernummer: 105 5891 1000 > > > Please consider that invitations and e-mails of our institute are > only valid if they end with …@mpie.de. > If you are not sure of the validity please contact r...@mpie.de > <mailto:r...@mpie.de> > > Bitte beachten Sie, dass Einladungen zu Veranstaltungen und E-Mails > aus unserem Haus nur mit der Endung …@mpie.de gültig sind. > In Zweifelsfällen wenden Sie sich bitte an r...@mpie.de <mailto:r...@mpie.de> > ------------------------------------------------- > > > > > ------------------------------------------------- > Stay up to date and follow us on LinkedIn, Twitter and YouTube. > > Max-Planck-Institut für Eisenforschung GmbH > Max-Planck-Straße 1 > D-40237 Düsseldorf > > Handelsregister B 2533 > Amtsgericht Düsseldorf > > Geschäftsführung > Prof. Dr. Gerhard Dehm > Prof. Dr. Jörg Neugebauer > Prof. Dr. Dierk Raabe > Dr. Kai de Weldige > > Ust.-Id.-Nr.: DE 11 93 58 514 > Steuernummer: 105 5891 1000 > > > Please consider that invitations and e-mails of our institute are > only valid if they end with …@mpie.de. > If you are not sure of the validity please contact r...@mpie.de > <mailto:r...@mpie.de> > > Bitte beachten Sie, dass Einladungen zu Veranstaltungen und E-Mails > aus unserem Haus nur mit der Endung …@mpie.de gültig sind. > In Zweifelsfällen wenden Sie sich bitte an r...@mpie.de <mailto:r...@mpie.de> > ------------------------------------------------- > > > > ------------------------------------------------- > Stay up to date and follow us on LinkedIn, Twitter and YouTube. > > Max-Planck-Institut für Eisenforschung GmbH > Max-Planck-Straße 1 > D-40237 Düsseldorf > > Handelsregister B 2533 > Amtsgericht Düsseldorf > > Geschäftsführung > Prof. Dr. Gerhard Dehm > Prof. Dr. Jörg Neugebauer > Prof. Dr. Dierk Raabe > Dr. Kai de Weldige > > Ust.-Id.-Nr.: DE 11 93 58 514 > Steuernummer: 105 5891 1000 > > > Please consider that invitations and e-mails of our institute are > only valid if they end with …@mpie.de. > If you are not sure of the validity please contact r...@mpie.de > <mailto:r...@mpie.de> > > Bitte beachten Sie, dass Einladungen zu Veranstaltungen und E-Mails > aus unserem Haus nur mit der Endung …@mpie.de gültig sind. > In Zweifelsfällen wenden Sie sich bitte an r...@mpie.de <mailto:r...@mpie.de> > ------------------------------------------------- > > > > ------------------------------------------------- > Stay up to date and follow us on LinkedIn, Twitter and YouTube. > > Max-Planck-Institut für Eisenforschung GmbH > Max-Planck-Straße 1 > D-40237 Düsseldorf > > Handelsregister B 2533 > Amtsgericht Düsseldorf > > Geschäftsführung > Prof. Dr. Gerhard Dehm > Prof. Dr. Jörg Neugebauer > Prof. Dr. Dierk Raabe > Dr. Kai de Weldige > > Ust.-Id.-Nr.: DE 11 93 58 514 > Steuernummer: 105 5891 1000 > > > Please consider that invitations and e-mails of our institute are > only valid if they end with …@mpie.de. > If you are not sure of the validity please contact r...@mpie.de > <mailto:r...@mpie.de> > > Bitte beachten Sie, dass Einladungen zu Veranstaltungen und E-Mails > aus unserem Haus nur mit der Endung …@mpie.de gültig sind. > In Zweifelsfällen wenden Sie sich bitte an r...@mpie.de <mailto:r...@mpie.de> > -------------------------------------------------