[petsc-users] Using SNESSHELL as a wrapper for a CFD solver.
Kenneth C Hall
kenneth.c.hall at duke.edu
Wed May 31 14:21:11 CDT 2023
Hi,
I am doing a number of problems using PETSc/SLEPc, but I also work on some non-PETSc/SLEPc flow solvers. I would like to use PETSc as a wrapper for this non-PETSc flow solver for compatibility, so I can use the tolerance monitoring, options, viewers, and for direct comparison to PETSc methods I am using.
Here is what I am trying to do… I have a CFD solver that iterates with a nonlinear iterator of the form x := N(x). This can be expressed in a fortran routine of the form,
SUBROUTINE MySolver(x)
or
SUBROUTINE MySolver(x,y)
In the first case, x is over written. In the second, y = N(x). In any event, I want to do something like what is shown in the subroutine at the bottom of this email.
The code below “works” in the sense that MySolver is called, but it is called exactly *once*. But MyMonitor and MyConverged are *not* called. Again, I want to iterate so MySolver should be called many times, as should MyMonitor and MyConverged.
The SNESView before and after SNESSolve looks like this:
SNES Object: 1 MPI process
type: shell
SNES has not been set up so information may be incomplete
maximum iterations=50, maximum function evaluations=10000
tolerances: relative=1e-50, absolute=1e-10, solution=1e+06
total number of function evaluations=0
norm schedule ALWAYS
SNES Object: 1 MPI process
type: shell
maximum iterations=50, maximum function evaluations=10000
tolerances: relative=1e-50, absolute=1e-10, solution=1e+06
total number of function evaluations=0
norm schedule ALWAYS
Any suggestions on how to do what I am trying to accomplish?
Thanks.
Kenneth Hall
#include <petsc/finclude/petsc.h>
#include "macros.h"
MODULE SolveWithSNESShell_module
USE MyPetscModule
CONTAINS
!
!====================================================================================================
SUBROUTINE MySolver(snes, x, ierr)
!====================================================================================================
!!
!!
!====================================================================================================
!
USE MyPetscModule
IMPLICIT NONE
!
!.... declared passed variables
SNES :: snes
Vec :: x
PetscErrorCode :: ierr
!
!.... code to find residual x := N(x)
!.... (or alternatively y := N(x))
END SUBROUTINE MySolver
!
!====================================================================================================
SUBROUTINE MyMonitor(snes, its, rnorm, ierr)
!====================================================================================================
!!
!!
!====================================================================================================
!
USE MyPetscModule
IMPLICIT NONE
!
!.... Declare passed variables
SNES :: snes
PetscInt :: its
PetscReal :: rnorm
PetscErrorCode :: ierr
!
!.... Code to print out convergence history
!.... Code to print out convergence history
END SUBROUTINE MyMonitor
!====================================================================================================
SUBROUTINE MyConverged(snes, it, xnorm, ynorm, znorm, reason, ierr)
USE MyPetscModule
IMPLICIT NONE
SNES :: snes
PetscInt :: it,ctx
PetscReal :: xnorm, ynorm, znorm
KSPConvergedReason :: reason
PetscErrorCode :: ierr
! ... add convergence test here ...
! set reason to a positive value if convergence has been achieved
END SUBROUTINE MyConverged
END MODULE SolveWithSNESShell_module
!
!====================================================================================================
SUBROUTINE SolveWithSNESShell
!====================================================================================================
!!
!!
!====================================================================================================
!
USE SolveWithSNESShell_module
IMPLICIT NONE
!
!.... Declare passed variables
INTEGER :: level_tmp
!
!.... Declare local variables
INTEGER :: iz
INTEGER :: imax
INTEGER :: jmax
INTEGER :: kmax
SNES :: snes
KSP :: ksp
Vec :: x
Vec :: y
PetscViewer :: viewer
PetscErrorCode :: ierr
PetscReal :: rtol = 1.0D-10 !! relative tolerance
PetscReal :: atol = 1.0D-50 !! absolute tolerance
PetscReal :: dtol = 1.0D+06 !! divergence tolerance
PetscInt :: maxits = 50
PetscInt :: maxf = 10000
character(len=1000):: args
!
!.... count the number of degrees of freedom.
level = level_tmp
n = 0
DO iz = 1, hb(level)%nzone
imax = hb(level)%zone(iz)%imax - 1
jmax = hb(level)%zone(iz)%jmax - 1
kmax = hb(level)%zone(iz)%kmax - 1
n = n + imax * jmax * kmax
END DO
n = n * neqn
!
!.... Initialize PETSc
PetscCall(PetscInitialize(PETSC_NULL_CHARACTER, ierr))
!
!.... Log
PetscCall(PetscLogDefaultBegin(ierr))
!
!.... Hard-wired options.
! PetscCall(PetscOptionsInsertString(PETSC_NULL_OPTIONS, "command line style option here" , ierr))
!
!.... Command line options.
call GET_COMMAND(args)
PetscCall(PetscOptionsInsertString(PETSC_NULL_OPTIONS, args, ierr))
!
!.... view command line table
PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, PETSC_VIEWER_STDOUT_SELF, viewer, ierr))
PetscCall(PetscOptionsView(PETSC_NULL_OPTIONS, viewer, ierr))
PetscCall(PetscViewerDestroy(viewer, ierr))
!
!.... Create PETSc vectors
PetscCall(VecCreateSeq(PETSC_COMM_SELF, n, x, ierr))
PetscCall(VecCreateSeq(PETSC_COMM_SELF, n, y, ierr))
PetscCall(VecSet(x, 0.0d0, ierr))
PetscCall(VecSet(y, 0.0d0, ierr))
!.... SNES context
PetscCall(SNESCreate(PETSC_COMM_SELF, snes, ierr))
PetscCall(SNESSetType(snes, SNESSHELL, ierr))
PetscCall(SNESShellSetSolve(snes, MySolver, ierr))
!!!! PetscCall(SNESSetFunction(snes, x, MySolver, PETSC_NULL_INTEGER, ierr))
!!!! this line causes a segmentation error if uncommented.
PetscCall(SNESSetConvergenceTest(snes, MyConverged, 0, PETSC_NULL_FUNCTION, ierr))
!
!.... Set SNES options
PetscCall(SNESSetFromOptions(snes, ierr))
!.... Set tolerances
PetscCall(SNESSetTolerances(snes, rtol, atol, dtol, maxits, maxf, ierr))
!
!.... SNES montior
PetscCall(SNESMonitorSet(snes, MyMonitor, PETSC_NULL_INTEGER, PETSC_NULL_FUNCTION,ierr))
!
!.... Set the initial solution
CALL HBToVecX(x)
!
!.... View snes context
PetscCall(SNESView(snes, viewer, ierr))
!
!.... Solve SNES problem
PetscCall(SNESSolve(snes, PETSC_NULL_VEC, x, ierr))
!
!.... View snes context
PetscCall(SNESView(snes, viewer, ierr))
!
!.... dump the logs
! call PetscLogDump(ierr) ! Why does this cause error
!
!.... Destroy PETSc objects
PetscCall(SNESDestroy(snes, ierr))
PetscCall(VecDestroy(x, ierr))
PetscCall(VecDestroy(y, ierr))
PetscCall(PetscViewerDestroy(viewer, ierr))
!
!.... Finish
PetscCall(PetscFinalize(ierr))
END SUBROUTINE SolveWithSNESShell
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mcs.anl.gov/pipermail/petsc-users/attachments/20230531/ba7df359/attachment-0001.html>
More information about the petsc-users
mailing list