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