[petsc-users] Matrix free SNES with user provided matrix vector product and preconditioner operation

Weide, Edwin van der (UT-ET) e.t.a.vanderweide at utwente.nl
Thu Nov 7 11:21:19 CST 2024


Yes, this works. Thanks a lot for your help.
Regards,

Edwin

________________________________
From: Barry Smith <bsmith at petsc.dev>
Sent: Wednesday, November 6, 2024 7:03 PM
To: Weide, Edwin van der (UT-ET) <e.t.a.vanderweide at utwente.nl>
Cc: petsc-users at mcs.anl.gov <petsc-users at mcs.anl.gov>
Subject: Re: [petsc-users] Matrix free SNES with user provided matrix vector product and preconditioner operation


  You need to provide a callback function. Why? Otherwise your MatShell and PCshell have no way of knowing at what location the Jacobian is suppose to be evaluated at (in a matrix free way). That is the x for which J(x) is used.

  Normally one puts the x into the application context of mJac and accesses it every time the matmult is called. Similarly it needs to be accessed in application of your preconditioner.



On Nov 6, 2024, at 12:01 PM, Weide, Edwin van der (UT-ET) <e.t.a.vanderweide at utwente.nl> wrote:

Barry,

If I do that, I get the following error

[0]PETSC ERROR: ------------------------------------------------------------------------
[0]PETSC ERROR: Caught signal number 11 SEGV: Segmentation Violation, probably memory access out of range
[0]PETSC ERROR: Try option -start_in_debugger or -on_error_attach_debugger
[0]PETSC ERROR: or see https://urldefense.us/v3/__https://petsc.org/release/faq/*valgrind__;Iw!!G_uCfscf7eWS!dfJ_L4Ay2QlfGz0JU6uAfD7Zy_6a7x9D0bisHMG1T53fTy_gWL3Q8fzzLvWZ_TBK37FFmDYerLywkFOLtMnU1rISfF_VA3gxsDTm$  and https://urldefense.us/v3/__https://petsc.org/release/faq/__;!!G_uCfscf7eWS!dfJ_L4Ay2QlfGz0JU6uAfD7Zy_6a7x9D0bisHMG1T53fTy_gWL3Q8fzzLvWZ_TBK37FFmDYerLywkFOLtMnU1rISfF_VAwRW4W44$ 
[0]PETSC ERROR: ---------------------  Stack Frames ------------------------------------
[0]PETSC ERROR: The line numbers in the error traceback are not always exact.
[0]PETSC ERROR: #1 SNES callback Jacobian
[0]PETSC ERROR: #2 SNESComputeJacobian() at /home/vdweide/petsc/src/snes/interface/snes.c:2966
[0]PETSC ERROR: #3 SNESSolve_NEWTONLS() at /home/vdweide/petsc/src/snes/impls/ls/ls.c:218
[0]PETSC ERROR: #4 SNESSolve() at /home/vdweide/petsc/src/snes/interface/snes.c:4841
[0]PETSC ERROR: #5 SolveCurrentStage() at SolverClass.cpp:502
[0]PETSC ERROR: #6 main() at Condensation.cpp:20
--------------------------------------------------------------------------

So SNES tries to call the call back function for the Jacobian, but that is not provided. Hence the failure.
Regards,

Edwin

________________________________
From: Barry Smith <bsmith at petsc.dev<mailto:bsmith at petsc.dev>>
Sent: Wednesday, November 6, 2024 5:52 PM
To: Weide, Edwin van der (UT-ET) <e.t.a.vanderweide at utwente.nl<mailto:e.t.a.vanderweide at utwente.nl>>
Cc: petsc-users at mcs.anl.gov<mailto:petsc-users at mcs.anl.gov> <petsc-users at mcs.anl.gov<mailto:petsc-users at mcs.anl.gov>>
Subject: Re: [petsc-users] Matrix free SNES with user provided matrix vector product and preconditioner operation


   Just pass mJac, mJac  instead of mJac, nullptr and it will be happy.  In your case, the second mJac  won't be used in your preconditioner it is just a place holder so other parts of SNES won't try to create a matrix.

  Barry


On Nov 6, 2024, at 11:36 AM, Weide, Edwin van der (UT-ET) via petsc-users <petsc-users at mcs.anl.gov<mailto:petsc-users at mcs.anl.gov>> wrote:

Hi,

I am trying to solve a nonlinear problem with matrix-free SNES where I would like to provide both the matrix vector product and the preconditioner myself. For that purpose, I use the following construction.

  // Set up the matrix free evaluation of the Jacobian times a vector
  // by setting the appropriate function in snes.
  PetscCall(MatCreateShell(PETSC_COMM_WORLD, PETSC_DECIDE, PETSC_DECIDE,
                           nEqns, nEqns, this, &mJac));
  PetscCall(MatShellSetOperation(mJac, MATOP_MULT,
                                 (void (*)(void))JacobianTimesVector));

  PetscCall(SNESSetJacobian(mSnes, mJac, nullptr, nullptr, nullptr));

  // Set the function to be used as preconditioner for the krylov solver.
  KSP ksp;
  PC  pc;
  PetscCall(SNESGetKSP(mSnes, &ksp));
  PetscCall(KSPGetPC(ksp, &pc));
  PetscCall(PCSetType(pc, PCSHELL));
  PetscCall(PCSetApplicationContext(pc, this));
  PetscCall(PCShellSetApply(pc, Preconditioner));

For small problems this construction works, and it does exactly what I expect it to do. However, when I increase the problem size, I get a memory allocation failure in SNESSolve, because it looks like SNES attempts to allocate memory for a full dense matrix for the preconditioner, which is not used. This is the call stack when the error occurs.

[0]PETSC ERROR: #1 PetscMallocAlign() at /home/vdweide/petsc/src/sys/memory/mal.c:53
[0]PETSC ERROR: #2 PetscTrMallocDefault() at /home/vdweide/petsc/src/sys/memory/mtr.c:175
[0]PETSC ERROR: #3 PetscMallocA() at /home/vdweide/petsc/src/sys/memory/mal.c:421
[0]PETSC ERROR: #4 MatSeqDenseSetPreallocation_SeqDense() at /home/vdweide/petsc/src/mat/impls/dense/seq/dense.c:3357
[0]PETSC ERROR: #5 MatSeqDenseSetPreallocation() at /home/vdweide/petsc/src/mat/impls/dense/seq/dense.c:3338
[0]PETSC ERROR: #6 MatDuplicateNoCreate_SeqDense() at /home/vdweide/petsc/src/mat/impls/dense/seq/dense.c:372
[0]PETSC ERROR: #7 MatDuplicate_SeqDense() at /home/vdweide/petsc/src/mat/impls/dense/seq/dense.c:399
[0]PETSC ERROR: #8 MatDuplicate() at /home/vdweide/petsc/src/mat/interface/matrix.c:4964
[0]PETSC ERROR: #9 DMCreateMatrix_Shell() at /home/vdweide/petsc/src/dm/impls/shell/dmshell.c:195
[0]PETSC ERROR: #10 DMCreateMatrix() at /home/vdweide/petsc/src/dm/interface/dm.c:1501
[0]PETSC ERROR: #11 SNESSetUpMatrices() at /home/vdweide/petsc/src/snes/interface/snes.c:794
[0]PETSC ERROR: #12 SNESSetUp_NEWTONLS() at /home/vdweide/petsc/src/snes/impls/ls/ls.c:290
[0]PETSC ERROR: #13 SNESSetUp() at /home/vdweide/petsc/src/snes/interface/snes.c:3395
[0]PETSC ERROR: #14 SNESSolve() at /home/vdweide/petsc/src/snes/interface/snes.c:4831
[0]PETSC ERROR: #15 SolveCurrentStage() at SolverClass.cpp:502

In the function SNESSetUpMatrices the source looks as follows

 784   } else if (!snes->jacobian_pre) {
 785     PetscDS   prob;
 786     Mat       J, B;
 787     PetscBool hasPrec = PETSC_FALSE;
 788
 789     J = snes->jacobian;
 790     PetscCall(DMGetDS(dm, &prob));
 791     if (prob) PetscCall(PetscDSHasJacobianPreconditioner(prob, &hasPrec));
 792     if (J) PetscCall(PetscObjectReference((PetscObject)J));
 793     else if (hasPrec) PetscCall(DMCreateMatrix(snes->dm, &J));
 794     PetscCall(DMCreateMatrix(snes->dm, &B));
 795     PetscCall(SNESSetJacobian(snes, J ? J : B, B, NULL, NULL));
 796     PetscCall(MatDestroy(&J));
 797     PetscCall(MatDestroy(&B));
 798   }

It looks like in line 794 it is attempted to create the preconditioner, because it was (intentionally) not provided.

Hence my question. Is it possible to use matrix-free SNES with a user provided matrix vector product (via MatShell) and a user provided preconditioner operation without SNES allocating the memory for a dense matrix? If so, what do I need to change in the construction above to make it work?

If needed, I can provide the source code for which this problem occurs.
Thanks,

Edwin

---------------------------------------------------
Edwin van der Weide
Department of Mechanical Engineering
University of Twente
Enschede, the Netherlands

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mcs.anl.gov/pipermail/petsc-users/attachments/20241107/8149a50c/attachment-0001.html>


More information about the petsc-users mailing list