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