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)) 54c4762a1bSJed Brown! dummy test of logging a reduction 55956f8c0dSBarry Smith#if defined(PETSC_USE_LOG) 56c4762a1bSJed Brown ierr = PetscAReduce() 57956f8c0dSBarry Smith#endif 58d8606c27SBarry Smith PetscCallMPIA(MPI_Comm_size(PETSC_COMM_WORLD,size,ierr)) 59d8606c27SBarry Smith PetscCallMPIA(MPI_Comm_rank(PETSC_COMM_WORLD,rank,ierr)) 60c4762a1bSJed Brown if (size .ne. 1) then; SETERRA(PETSC_COMM_SELF,PETSC_ERR_WRONG_MPI_SIZE,'Uniprocessor example'); endif 61c4762a1bSJed Brown 62c4762a1bSJed Brown i2 = 2 63c4762a1bSJed Brown i20 = 20 64c4762a1bSJed Brown! - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - 65c4762a1bSJed Brown! Create nonlinear solver context 66c4762a1bSJed Brown! - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - 67c4762a1bSJed Brown 68d8606c27SBarry Smith PetscCallA(SNESCreate(PETSC_COMM_WORLD,snes,ierr)) 69c4762a1bSJed Brown 70c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 71c4762a1bSJed Brown! Create matrix and vector data structures; set corresponding routines 72c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 73c4762a1bSJed Brown 74c4762a1bSJed Brown! Create vectors for solution and nonlinear function 75c4762a1bSJed Brown 76d8606c27SBarry Smith PetscCallA(VecCreateSeq(PETSC_COMM_SELF,i2,x,ierr)) 77d8606c27SBarry Smith PetscCallA(VecDuplicate(x,r,ierr)) 78c4762a1bSJed Brown 79c4762a1bSJed Brown! Create Jacobian matrix data structure 80c4762a1bSJed Brown 81d8606c27SBarry Smith PetscCallA(MatCreate(PETSC_COMM_SELF,J,ierr)) 82d8606c27SBarry Smith PetscCallA(MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,i2,i2,ierr)) 83d8606c27SBarry Smith PetscCallA(MatSetFromOptions(J,ierr)) 84d8606c27SBarry Smith PetscCallA(MatSetUp(J,ierr)) 85c4762a1bSJed Brown 86c4762a1bSJed Brown! Set function evaluation routine and vector 87c4762a1bSJed Brown 88d8606c27SBarry Smith PetscCallA(SNESSetFunction(snes,r,FormFunction,0,ierr)) 89c4762a1bSJed Brown 90c4762a1bSJed Brown! Set Jacobian matrix data structure and Jacobian evaluation routine 91c4762a1bSJed Brown 92d8606c27SBarry Smith PetscCallA(SNESSetJacobian(snes,J,J,FormJacobian,0,ierr)) 93c4762a1bSJed Brown 94c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 95c4762a1bSJed Brown! Customize nonlinear solver; set runtime options 96c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 97c4762a1bSJed Brown 98c4762a1bSJed Brown! Set linear solver defaults for this problem. By extracting the 99c4762a1bSJed Brown! KSP, KSP, and PC contexts from the SNES context, we can then 100c4762a1bSJed Brown! directly call any KSP, KSP, and PC routines to set various options. 101c4762a1bSJed Brown 102d8606c27SBarry Smith PetscCallA(SNESGetKSP(snes,ksp,ierr)) 103d8606c27SBarry Smith PetscCallA(KSPGetPC(ksp,pc,ierr)) 104d8606c27SBarry Smith PetscCallA(PCSetType(pc,PCNONE,ierr)) 105c4762a1bSJed Brown tol = 1.e-4 106d8606c27SBarry Smith PetscCallA(KSPSetTolerances(ksp,tol,PETSC_DEFAULT_REAL,PETSC_DEFAULT_REAL,i20,ierr)) 107c4762a1bSJed Brown 108c4762a1bSJed Brown! Set SNES/KSP/KSP/PC runtime options, e.g., 109c4762a1bSJed Brown! -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc> 110c4762a1bSJed Brown! These options will override those specified above as long as 111c4762a1bSJed Brown! SNESSetFromOptions() is called _after_ any other customization 112c4762a1bSJed Brown! routines. 113c4762a1bSJed Brown 114d8606c27SBarry Smith PetscCallA(SNESSetFromOptions(snes,ierr)) 115c4762a1bSJed Brown 116d8606c27SBarry Smith PetscCallA(PetscOptionsHasName(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-setls',setls,ierr)) 117c4762a1bSJed Brown 118c4762a1bSJed Brown if (setls) then 119d8606c27SBarry Smith PetscCallA(SNESGetLineSearch(snes, linesearch, ierr)) 120d8606c27SBarry Smith PetscCallA(SNESLineSearchSetType(linesearch, 'shell', ierr)) 121d8606c27SBarry Smith PetscCallA(SNESLineSearchShellSetUserFunc(linesearch, MyLineSearch,0,ierr)) 122c4762a1bSJed Brown endif 123c4762a1bSJed Brown 124c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 125c4762a1bSJed Brown! Evaluate initial guess; then solve nonlinear system 126c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 127c4762a1bSJed Brown 128c4762a1bSJed Brown! Note: The user should initialize the vector, x, with the initial guess 129c4762a1bSJed Brown! for the nonlinear solver prior to calling SNESSolve(). In particular, 130c4762a1bSJed Brown! to employ an initial guess of zero, the user should explicitly set 131c4762a1bSJed Brown! this vector to zero by calling VecSet(). 132c4762a1bSJed Brown 133c4762a1bSJed Brown pfive = 0.5 134d8606c27SBarry Smith PetscCallA(VecSet(x,pfive,ierr)) 135d8606c27SBarry Smith PetscCallA(SNESSolve(snes,PETSC_NULL_VEC,x,ierr)) 13691f3e32bSBarry Smith 13791f3e32bSBarry Smith! View solver converged reason; we could instead use the option -snes_converged_reason 138d8606c27SBarry Smith PetscCallA(SNESConvergedReasonView(snes,PETSC_VIEWER_STDOUT_WORLD,ierr)) 13991f3e32bSBarry Smith 140d8606c27SBarry Smith PetscCallA(SNESGetIterationNumber(snes,its,ierr)) 141c4762a1bSJed Brown if (rank .eq. 0) then 142c4762a1bSJed Brown write(6,100) its 143c4762a1bSJed Brown endif 144c4762a1bSJed Brown 100 format('Number of SNES iterations = ',i5) 145c4762a1bSJed Brown 146c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 147c4762a1bSJed Brown! Free work space. All PETSc objects should be destroyed when they 148c4762a1bSJed Brown! are no longer needed. 149c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 150c4762a1bSJed Brown 151d8606c27SBarry Smith PetscCallA(VecDestroy(x,ierr)) 152d8606c27SBarry Smith PetscCallA(VecDestroy(r,ierr)) 153d8606c27SBarry Smith PetscCallA(MatDestroy(J,ierr)) 154d8606c27SBarry Smith PetscCallA(SNESDestroy(snes,ierr)) 155956f8c0dSBarry Smith#if defined(PETSC_USE_LOG) 156d8606c27SBarry Smith PetscCallA(PetscViewerASCIIOpen(PETSC_COMM_WORLD,'filename.xml',viewer,ierr)) 157d8606c27SBarry Smith PetscCallA(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_XML,ierr)) 158d8606c27SBarry Smith PetscCallA(PetscLogView(viewer,ierr)) 159d8606c27SBarry Smith PetscCallA(PetscViewerDestroy(viewer,ierr)) 160956f8c0dSBarry Smith#endif 161d8606c27SBarry Smith PetscCallA(PetscFinalize(ierr)) 162c4762a1bSJed Brown end 163c4762a1bSJed Brown! 164c4762a1bSJed Brown! ------------------------------------------------------------------------ 165c4762a1bSJed Brown! 166c4762a1bSJed Brown! FormFunction - Evaluates nonlinear function, F(x). 167c4762a1bSJed Brown! 168c4762a1bSJed Brown! Input Parameters: 169c4762a1bSJed Brown! snes - the SNES context 170c4762a1bSJed Brown! x - input vector 171c4762a1bSJed Brown! dummy - optional user-defined context (not used here) 172c4762a1bSJed Brown! 173c4762a1bSJed Brown! Output Parameter: 174c4762a1bSJed Brown! f - function vector 175c4762a1bSJed Brown! 176c4762a1bSJed Brown subroutine FormFunction(snes,x,f,dummy,ierr) 177c4762a1bSJed Brown use petscsnes 178c4762a1bSJed Brown implicit none 179c4762a1bSJed Brown 180c4762a1bSJed Brown SNES snes 181c4762a1bSJed Brown Vec x,f 182c4762a1bSJed Brown PetscErrorCode ierr 183c4762a1bSJed Brown integer dummy(*) 184c4762a1bSJed Brown 185c4762a1bSJed Brown! Declarations for use with local arrays 186*42ce371bSBarry Smith PetscScalar,pointer :: lx_v(:),lf_v(:) 187c4762a1bSJed Brown 188c4762a1bSJed Brown! Get pointers to vector data. 189*42ce371bSBarry Smith! - VecGetArrayF90() returns a pointer to the data array. 190*42ce371bSBarry Smith! - You MUST call VecRestoreArrayF90() when you no longer need access to 191c4762a1bSJed Brown! the array. 192c4762a1bSJed Brown 193*42ce371bSBarry Smith PetscCall(VecGetArrayReadF90(x,lx_v,ierr)) 194*42ce371bSBarry Smith PetscCall(VecGetArrayF90(f,lf_v,ierr)) 195c4762a1bSJed Brown 196c4762a1bSJed Brown! Compute function 197c4762a1bSJed Brown 198*42ce371bSBarry Smith lf_v(1) = lx_v(1)*lx_v(1) + lx_v(1)*lx_v(2) - 3.0 199*42ce371bSBarry Smith lf_v(2) = lx_v(1)*lx_v(2) + lx_v(2)*lx_v(2) - 6.0 200c4762a1bSJed Brown 201c4762a1bSJed Brown! Restore vectors 202c4762a1bSJed Brown 203*42ce371bSBarry Smith PetscCall(VecRestoreArrayReadF90(x,lx_v,ierr)) 204*42ce371bSBarry Smith PetscCall(VecRestoreArrayF90(f,lf_v,ierr)) 205c4762a1bSJed Brown 206c4762a1bSJed Brown return 207c4762a1bSJed Brown end 208c4762a1bSJed Brown 209c4762a1bSJed Brown! --------------------------------------------------------------------- 210c4762a1bSJed Brown! 211c4762a1bSJed Brown! FormJacobian - Evaluates Jacobian matrix. 212c4762a1bSJed Brown! 213c4762a1bSJed Brown! Input Parameters: 214c4762a1bSJed Brown! snes - the SNES context 215c4762a1bSJed Brown! x - input vector 216c4762a1bSJed Brown! dummy - optional user-defined context (not used here) 217c4762a1bSJed Brown! 218c4762a1bSJed Brown! Output Parameters: 219c4762a1bSJed Brown! A - Jacobian matrix 220c4762a1bSJed Brown! B - optionally different preconditioning matrix 221c4762a1bSJed Brown! 222c4762a1bSJed Brown subroutine FormJacobian(snes,X,jac,B,dummy,ierr) 223c4762a1bSJed Brown use petscsnes 224c4762a1bSJed Brown implicit none 225c4762a1bSJed Brown 226c4762a1bSJed Brown SNES snes 227c4762a1bSJed Brown Vec X 228c4762a1bSJed Brown Mat jac,B 229c4762a1bSJed Brown PetscScalar A(4) 230c4762a1bSJed Brown PetscErrorCode ierr 231c4762a1bSJed Brown PetscInt idx(2),i2 232c4762a1bSJed Brown integer dummy(*) 233c4762a1bSJed Brown 234c4762a1bSJed Brown! Declarations for use with local arrays 235c4762a1bSJed Brown 236*42ce371bSBarry Smith PetscScalar,pointer :: lx_v(:) 237c4762a1bSJed Brown 238c4762a1bSJed Brown! Get pointer to vector data 239c4762a1bSJed Brown 240c4762a1bSJed Brown i2 = 2 241*42ce371bSBarry Smith PetscCall(VecGetArrayReadF90(x,lx_v,ierr)) 242c4762a1bSJed Brown 243c4762a1bSJed Brown! Compute Jacobian entries and insert into matrix. 244c4762a1bSJed Brown! - Since this is such a small problem, we set all entries for 245c4762a1bSJed Brown! the matrix at once. 246c4762a1bSJed Brown! - Note that MatSetValues() uses 0-based row and column numbers 247c4762a1bSJed Brown! in Fortran as well as in C (as set here in the array idx). 248c4762a1bSJed Brown 249c4762a1bSJed Brown idx(1) = 0 250c4762a1bSJed Brown idx(2) = 1 251*42ce371bSBarry Smith A(1) = 2.0*lx_v(1) + lx_v(2) 252*42ce371bSBarry Smith A(2) = lx_v(1) 253*42ce371bSBarry Smith A(3) = lx_v(2) 254*42ce371bSBarry Smith A(4) = lx_v(1) + 2.0*lx_v(2) 255d8606c27SBarry Smith PetscCall(MatSetValues(B,i2,idx,i2,idx,A,INSERT_VALUES,ierr)) 256c4762a1bSJed Brown 257c4762a1bSJed Brown! Restore vector 258c4762a1bSJed Brown 259*42ce371bSBarry Smith PetscCall(VecRestoreArrayReadF90(x,lx_v,ierr)) 260c4762a1bSJed Brown 261c4762a1bSJed Brown! Assemble matrix 262c4762a1bSJed Brown 263d8606c27SBarry Smith PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY,ierr)) 264d8606c27SBarry Smith PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY,ierr)) 265c4762a1bSJed Brown if (B .ne. jac) then 266d8606c27SBarry Smith PetscCall(MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY,ierr)) 267d8606c27SBarry Smith PetscCall(MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY,ierr)) 268c4762a1bSJed Brown endif 269c4762a1bSJed Brown 270c4762a1bSJed Brown return 271c4762a1bSJed Brown end 272c4762a1bSJed Brown 273c4762a1bSJed Brown subroutine MyLineSearch(linesearch, lctx, ierr) 274c4762a1bSJed Brown use petscsnes 275c4762a1bSJed Brown implicit none 276c4762a1bSJed Brown 277c4762a1bSJed Brown SNESLineSearch linesearch 278c4762a1bSJed Brown SNES snes 279c4762a1bSJed Brown integer lctx 280c4762a1bSJed Brown Vec x, f,g, y, w 281c4762a1bSJed Brown PetscReal ynorm,gnorm,xnorm 282c4762a1bSJed Brown PetscErrorCode ierr 283c4762a1bSJed Brown 284c4762a1bSJed Brown PetscScalar mone 285c4762a1bSJed Brown 286c4762a1bSJed Brown mone = -1.0 287d8606c27SBarry Smith PetscCall(SNESLineSearchGetSNES(linesearch, snes, ierr)) 288d8606c27SBarry Smith PetscCall(SNESLineSearchGetVecs(linesearch, x, f, y, w, g, ierr)) 289d8606c27SBarry Smith PetscCall(VecNorm(y,NORM_2,ynorm,ierr)) 290d8606c27SBarry Smith PetscCall(VecAXPY(x,mone,y,ierr)) 291d8606c27SBarry Smith PetscCall(SNESComputeFunction(snes,x,f,ierr)) 292d8606c27SBarry Smith PetscCall(VecNorm(f,NORM_2,gnorm,ierr)) 293d8606c27SBarry Smith PetscCall(VecNorm(x,NORM_2,xnorm,ierr)) 294d8606c27SBarry Smith PetscCall(VecNorm(y,NORM_2,ynorm,ierr)) 295d8606c27SBarry Smith PetscCall(SNESLineSearchSetNorms(linesearch, xnorm, gnorm, ynorm,ierr)) 296c4762a1bSJed Brown return 297c4762a1bSJed Brown end 298c4762a1bSJed Brown 299c4762a1bSJed Brown!/*TEST 300c4762a1bSJed Brown! 301c4762a1bSJed Brown! test: 302c4762a1bSJed Brown! args: -ksp_gmres_cgs_refinement_type refine_always -snes_monitor_short 303c4762a1bSJed Brown! requires: !single 304c4762a1bSJed Brown! 305c4762a1bSJed Brown!TEST*/ 306