1c4762a1bSJed Brown! 2c4762a1bSJed Brown! 3c4762a1bSJed Brown! Description: Uses the Newton method to solve a two-variable system. 4c4762a1bSJed Brown! 5c4762a1bSJed Brown 6c4762a1bSJed Brown program main 7c4762a1bSJed Brown#include <petsc/finclude/petsc.h> 8c4762a1bSJed Brown use petsc 9c4762a1bSJed Brown implicit none 10c4762a1bSJed Brown 11c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 12c4762a1bSJed Brown! Variable declarations 13c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 14c4762a1bSJed Brown! 15c4762a1bSJed Brown! Variables: 16c4762a1bSJed Brown! snes - nonlinear solver 17c4762a1bSJed Brown! ksp - linear solver 18c4762a1bSJed Brown! pc - preconditioner context 19c4762a1bSJed Brown! ksp - Krylov subspace method context 20c4762a1bSJed Brown! x, r - solution, residual vectors 21c4762a1bSJed Brown! J - Jacobian matrix 22c4762a1bSJed Brown! its - iterations for convergence 23c4762a1bSJed Brown! 24c4762a1bSJed Brown SNES snes 25c4762a1bSJed Brown PC pc 26c4762a1bSJed Brown KSP ksp 27c4762a1bSJed Brown Vec x,r 28c4762a1bSJed Brown Mat J 29c4762a1bSJed Brown SNESLineSearch linesearch 30c4762a1bSJed Brown PetscErrorCode ierr 31c4762a1bSJed Brown PetscInt its,i2,i20 32c4762a1bSJed Brown PetscMPIInt size,rank 33c4762a1bSJed Brown PetscScalar pfive 34c4762a1bSJed Brown PetscReal tol 35c4762a1bSJed Brown PetscBool setls 36956f8c0dSBarry Smith#if defined(PETSC_USE_LOG) 37c4762a1bSJed Brown PetscViewer viewer 38956f8c0dSBarry Smith#endif 39c4762a1bSJed Brown double precision threshold,oldthreshold 40c4762a1bSJed Brown 41c4762a1bSJed Brown! Note: Any user-defined Fortran routines (such as FormJacobian) 42c4762a1bSJed Brown! MUST be declared as external. 43c4762a1bSJed Brown 44c4762a1bSJed Brown external FormFunction, FormJacobian, MyLineSearch 45c4762a1bSJed Brown 46c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 47c4762a1bSJed Brown! Beginning of program 48c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 49c4762a1bSJed Brown 50d8606c27SBarry Smith PetscCallA(PetscInitialize(ierr)) 51d8606c27SBarry Smith PetscCallA(PetscLogNestedBegin(ierr)) 52c4762a1bSJed Brown threshold = 1.0 53d8606c27SBarry Smith PetscCallA(PetscLogSetThreshold(threshold,oldthreshold,ierr)) 54d8606c27SBarry Smith PetscCallMPIA(MPI_Comm_size(PETSC_COMM_WORLD,size,ierr)) 55d8606c27SBarry Smith PetscCallMPIA(MPI_Comm_rank(PETSC_COMM_WORLD,rank,ierr)) 56dcb3e689SBarry Smith PetscCheckA(size .eq. 1,PETSC_COMM_SELF,PETSC_ERR_WRONG_MPI_SIZE,'Uniprocessor example') 57c4762a1bSJed Brown 58c4762a1bSJed Brown i2 = 2 59c4762a1bSJed Brown i20 = 20 60c4762a1bSJed Brown! - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - 61c4762a1bSJed Brown! Create nonlinear solver context 62c4762a1bSJed Brown! - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - 63c4762a1bSJed Brown 64d8606c27SBarry Smith PetscCallA(SNESCreate(PETSC_COMM_WORLD,snes,ierr)) 65c4762a1bSJed Brown 66c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 67c4762a1bSJed Brown! Create matrix and vector data structures; set corresponding routines 68c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 69c4762a1bSJed Brown 70c4762a1bSJed Brown! Create vectors for solution and nonlinear function 71c4762a1bSJed Brown 72d8606c27SBarry Smith PetscCallA(VecCreateSeq(PETSC_COMM_SELF,i2,x,ierr)) 73d8606c27SBarry Smith PetscCallA(VecDuplicate(x,r,ierr)) 74c4762a1bSJed Brown 75c4762a1bSJed Brown! Create Jacobian matrix data structure 76c4762a1bSJed Brown 77d8606c27SBarry Smith PetscCallA(MatCreate(PETSC_COMM_SELF,J,ierr)) 78d8606c27SBarry Smith PetscCallA(MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,i2,i2,ierr)) 79d8606c27SBarry Smith PetscCallA(MatSetFromOptions(J,ierr)) 80d8606c27SBarry Smith PetscCallA(MatSetUp(J,ierr)) 81c4762a1bSJed Brown 82c4762a1bSJed Brown! Set function evaluation routine and vector 83c4762a1bSJed Brown 84d8606c27SBarry Smith PetscCallA(SNESSetFunction(snes,r,FormFunction,0,ierr)) 85c4762a1bSJed Brown 86c4762a1bSJed Brown! Set Jacobian matrix data structure and Jacobian evaluation routine 87c4762a1bSJed Brown 88d8606c27SBarry Smith PetscCallA(SNESSetJacobian(snes,J,J,FormJacobian,0,ierr)) 89c4762a1bSJed Brown 90c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 91c4762a1bSJed Brown! Customize nonlinear solver; set runtime options 92c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 93c4762a1bSJed Brown 94c4762a1bSJed Brown! Set linear solver defaults for this problem. By extracting the 95c4762a1bSJed Brown! KSP, KSP, and PC contexts from the SNES context, we can then 96c4762a1bSJed Brown! directly call any KSP, KSP, and PC routines to set various options. 97c4762a1bSJed Brown 98d8606c27SBarry Smith PetscCallA(SNESGetKSP(snes,ksp,ierr)) 99d8606c27SBarry Smith PetscCallA(KSPGetPC(ksp,pc,ierr)) 100d8606c27SBarry Smith PetscCallA(PCSetType(pc,PCNONE,ierr)) 101c4762a1bSJed Brown tol = 1.e-4 102d8606c27SBarry Smith PetscCallA(KSPSetTolerances(ksp,tol,PETSC_DEFAULT_REAL,PETSC_DEFAULT_REAL,i20,ierr)) 103c4762a1bSJed Brown 104c4762a1bSJed Brown! Set SNES/KSP/KSP/PC runtime options, e.g., 105c4762a1bSJed Brown! -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc> 106c4762a1bSJed Brown! These options will override those specified above as long as 107c4762a1bSJed Brown! SNESSetFromOptions() is called _after_ any other customization 108c4762a1bSJed Brown! routines. 109c4762a1bSJed Brown 110d8606c27SBarry Smith PetscCallA(SNESSetFromOptions(snes,ierr)) 111c4762a1bSJed Brown 112d8606c27SBarry Smith PetscCallA(PetscOptionsHasName(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-setls',setls,ierr)) 113c4762a1bSJed Brown 114c4762a1bSJed Brown if (setls) then 115d8606c27SBarry Smith PetscCallA(SNESGetLineSearch(snes, linesearch, ierr)) 116d8606c27SBarry Smith PetscCallA(SNESLineSearchSetType(linesearch, 'shell', ierr)) 117*9bcc50f1SBarry Smith PetscCallA(SNESLineSearchShellSetApply(linesearch, MyLineSearch,0,ierr)) 118c4762a1bSJed Brown endif 119c4762a1bSJed Brown 120c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 121c4762a1bSJed Brown! Evaluate initial guess; then solve nonlinear system 122c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 123c4762a1bSJed Brown 124c4762a1bSJed Brown! Note: The user should initialize the vector, x, with the initial guess 125c4762a1bSJed Brown! for the nonlinear solver prior to calling SNESSolve(). In particular, 126c4762a1bSJed Brown! to employ an initial guess of zero, the user should explicitly set 127c4762a1bSJed Brown! this vector to zero by calling VecSet(). 128c4762a1bSJed Brown 129c4762a1bSJed Brown pfive = 0.5 130d8606c27SBarry Smith PetscCallA(VecSet(x,pfive,ierr)) 131d8606c27SBarry Smith PetscCallA(SNESSolve(snes,PETSC_NULL_VEC,x,ierr)) 13291f3e32bSBarry Smith 13391f3e32bSBarry Smith! View solver converged reason; we could instead use the option -snes_converged_reason 134d8606c27SBarry Smith PetscCallA(SNESConvergedReasonView(snes,PETSC_VIEWER_STDOUT_WORLD,ierr)) 13591f3e32bSBarry Smith 136d8606c27SBarry Smith PetscCallA(SNESGetIterationNumber(snes,its,ierr)) 137c4762a1bSJed Brown if (rank .eq. 0) then 138c4762a1bSJed Brown write(6,100) its 139c4762a1bSJed Brown endif 140c4762a1bSJed Brown 100 format('Number of SNES iterations = ',i5) 141c4762a1bSJed Brown 142c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 143c4762a1bSJed Brown! Free work space. All PETSc objects should be destroyed when they 144c4762a1bSJed Brown! are no longer needed. 145c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 146c4762a1bSJed Brown 147d8606c27SBarry Smith PetscCallA(VecDestroy(x,ierr)) 148d8606c27SBarry Smith PetscCallA(VecDestroy(r,ierr)) 149d8606c27SBarry Smith PetscCallA(MatDestroy(J,ierr)) 150d8606c27SBarry Smith PetscCallA(SNESDestroy(snes,ierr)) 151956f8c0dSBarry Smith#if defined(PETSC_USE_LOG) 152d8606c27SBarry Smith PetscCallA(PetscViewerASCIIOpen(PETSC_COMM_WORLD,'filename.xml',viewer,ierr)) 153d8606c27SBarry Smith PetscCallA(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_XML,ierr)) 154d8606c27SBarry Smith PetscCallA(PetscLogView(viewer,ierr)) 155d8606c27SBarry Smith PetscCallA(PetscViewerDestroy(viewer,ierr)) 156956f8c0dSBarry Smith#endif 157d8606c27SBarry Smith PetscCallA(PetscFinalize(ierr)) 158c4762a1bSJed Brown end 159c4762a1bSJed Brown! 160c4762a1bSJed Brown! ------------------------------------------------------------------------ 161c4762a1bSJed Brown! 162c4762a1bSJed Brown! FormFunction - Evaluates nonlinear function, F(x). 163c4762a1bSJed Brown! 164c4762a1bSJed Brown! Input Parameters: 165c4762a1bSJed Brown! snes - the SNES context 166c4762a1bSJed Brown! x - input vector 167c4762a1bSJed Brown! dummy - optional user-defined context (not used here) 168c4762a1bSJed Brown! 169c4762a1bSJed Brown! Output Parameter: 170c4762a1bSJed Brown! f - function vector 171c4762a1bSJed Brown! 172c4762a1bSJed Brown subroutine FormFunction(snes,x,f,dummy,ierr) 173c4762a1bSJed Brown use petscsnes 174c4762a1bSJed Brown implicit none 175c4762a1bSJed Brown 176c4762a1bSJed Brown SNES snes 177c4762a1bSJed Brown Vec x,f 178c4762a1bSJed Brown PetscErrorCode ierr 179c4762a1bSJed Brown integer dummy(*) 180c4762a1bSJed Brown 181c4762a1bSJed Brown! Declarations for use with local arrays 18242ce371bSBarry Smith PetscScalar,pointer :: lx_v(:),lf_v(:) 183c4762a1bSJed Brown 184c4762a1bSJed Brown! Get pointers to vector data. 18542ce371bSBarry Smith! - VecGetArrayF90() returns a pointer to the data array. 18642ce371bSBarry Smith! - You MUST call VecRestoreArrayF90() when you no longer need access to 187c4762a1bSJed Brown! the array. 188c4762a1bSJed Brown 18942ce371bSBarry Smith PetscCall(VecGetArrayReadF90(x,lx_v,ierr)) 19042ce371bSBarry Smith PetscCall(VecGetArrayF90(f,lf_v,ierr)) 191c4762a1bSJed Brown 192c4762a1bSJed Brown! Compute function 193c4762a1bSJed Brown 19442ce371bSBarry Smith lf_v(1) = lx_v(1)*lx_v(1) + lx_v(1)*lx_v(2) - 3.0 19542ce371bSBarry Smith lf_v(2) = lx_v(1)*lx_v(2) + lx_v(2)*lx_v(2) - 6.0 196c4762a1bSJed Brown 197c4762a1bSJed Brown! Restore vectors 198c4762a1bSJed Brown 19942ce371bSBarry Smith PetscCall(VecRestoreArrayReadF90(x,lx_v,ierr)) 20042ce371bSBarry Smith PetscCall(VecRestoreArrayF90(f,lf_v,ierr)) 201c4762a1bSJed Brown 202c4762a1bSJed Brown return 203c4762a1bSJed Brown end 204c4762a1bSJed Brown 205c4762a1bSJed Brown! --------------------------------------------------------------------- 206c4762a1bSJed Brown! 207c4762a1bSJed Brown! FormJacobian - Evaluates Jacobian matrix. 208c4762a1bSJed Brown! 209c4762a1bSJed Brown! Input Parameters: 210c4762a1bSJed Brown! snes - the SNES context 211c4762a1bSJed Brown! x - input vector 212c4762a1bSJed Brown! dummy - optional user-defined context (not used here) 213c4762a1bSJed Brown! 214c4762a1bSJed Brown! Output Parameters: 215c4762a1bSJed Brown! A - Jacobian matrix 216c4762a1bSJed Brown! B - optionally different preconditioning matrix 217c4762a1bSJed Brown! 218c4762a1bSJed Brown subroutine FormJacobian(snes,X,jac,B,dummy,ierr) 219c4762a1bSJed Brown use petscsnes 220c4762a1bSJed Brown implicit none 221c4762a1bSJed Brown 222c4762a1bSJed Brown SNES snes 223c4762a1bSJed Brown Vec X 224c4762a1bSJed Brown Mat jac,B 225c4762a1bSJed Brown PetscScalar A(4) 226c4762a1bSJed Brown PetscErrorCode ierr 227c4762a1bSJed Brown PetscInt idx(2),i2 228c4762a1bSJed Brown integer dummy(*) 229c4762a1bSJed Brown 230c4762a1bSJed Brown! Declarations for use with local arrays 231c4762a1bSJed Brown 23242ce371bSBarry Smith PetscScalar,pointer :: lx_v(:) 233c4762a1bSJed Brown 234c4762a1bSJed Brown! Get pointer to vector data 235c4762a1bSJed Brown 236c4762a1bSJed Brown i2 = 2 23742ce371bSBarry Smith PetscCall(VecGetArrayReadF90(x,lx_v,ierr)) 238c4762a1bSJed Brown 239c4762a1bSJed Brown! Compute Jacobian entries and insert into matrix. 240c4762a1bSJed Brown! - Since this is such a small problem, we set all entries for 241c4762a1bSJed Brown! the matrix at once. 242c4762a1bSJed Brown! - Note that MatSetValues() uses 0-based row and column numbers 243c4762a1bSJed Brown! in Fortran as well as in C (as set here in the array idx). 244c4762a1bSJed Brown 245c4762a1bSJed Brown idx(1) = 0 246c4762a1bSJed Brown idx(2) = 1 24742ce371bSBarry Smith A(1) = 2.0*lx_v(1) + lx_v(2) 24842ce371bSBarry Smith A(2) = lx_v(1) 24942ce371bSBarry Smith A(3) = lx_v(2) 25042ce371bSBarry Smith A(4) = lx_v(1) + 2.0*lx_v(2) 251d8606c27SBarry Smith PetscCall(MatSetValues(B,i2,idx,i2,idx,A,INSERT_VALUES,ierr)) 252c4762a1bSJed Brown 253c4762a1bSJed Brown! Restore vector 254c4762a1bSJed Brown 25542ce371bSBarry Smith PetscCall(VecRestoreArrayReadF90(x,lx_v,ierr)) 256c4762a1bSJed Brown 257c4762a1bSJed Brown! Assemble matrix 258c4762a1bSJed Brown 259d8606c27SBarry Smith PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY,ierr)) 260d8606c27SBarry Smith PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY,ierr)) 261c4762a1bSJed Brown if (B .ne. jac) then 262d8606c27SBarry Smith PetscCall(MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY,ierr)) 263d8606c27SBarry Smith PetscCall(MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY,ierr)) 264c4762a1bSJed Brown endif 265c4762a1bSJed Brown 266c4762a1bSJed Brown return 267c4762a1bSJed Brown end 268c4762a1bSJed Brown 269c4762a1bSJed Brown subroutine MyLineSearch(linesearch, lctx, ierr) 270c4762a1bSJed Brown use petscsnes 271c4762a1bSJed Brown implicit none 272c4762a1bSJed Brown 273c4762a1bSJed Brown SNESLineSearch linesearch 274c4762a1bSJed Brown SNES snes 275c4762a1bSJed Brown integer lctx 276c4762a1bSJed Brown Vec x, f,g, y, w 277c4762a1bSJed Brown PetscReal ynorm,gnorm,xnorm 278c4762a1bSJed Brown PetscErrorCode ierr 279c4762a1bSJed Brown 280c4762a1bSJed Brown PetscScalar mone 281c4762a1bSJed Brown 282c4762a1bSJed Brown mone = -1.0 283d8606c27SBarry Smith PetscCall(SNESLineSearchGetSNES(linesearch, snes, ierr)) 284d8606c27SBarry Smith PetscCall(SNESLineSearchGetVecs(linesearch, x, f, y, w, g, ierr)) 285d8606c27SBarry Smith PetscCall(VecNorm(y,NORM_2,ynorm,ierr)) 286d8606c27SBarry Smith PetscCall(VecAXPY(x,mone,y,ierr)) 287d8606c27SBarry Smith PetscCall(SNESComputeFunction(snes,x,f,ierr)) 288d8606c27SBarry Smith PetscCall(VecNorm(f,NORM_2,gnorm,ierr)) 289d8606c27SBarry Smith PetscCall(VecNorm(x,NORM_2,xnorm,ierr)) 290d8606c27SBarry Smith PetscCall(VecNorm(y,NORM_2,ynorm,ierr)) 291d8606c27SBarry Smith PetscCall(SNESLineSearchSetNorms(linesearch, xnorm, gnorm, ynorm,ierr)) 292c4762a1bSJed Brown return 293c4762a1bSJed Brown end 294c4762a1bSJed Brown 295c4762a1bSJed Brown!/*TEST 296c4762a1bSJed Brown! 297c4762a1bSJed Brown! test: 298c4762a1bSJed Brown! args: -ksp_gmres_cgs_refinement_type refine_always -snes_monitor_short 299c4762a1bSJed Brown! requires: !single 300c4762a1bSJed Brown! 301c4762a1bSJed Brown!TEST*/ 302