1c4762a1bSJed Brown! 2c4762a1bSJed Brown! Description: Uses the Newton method to solve a two-variable system. 3c4762a1bSJed Brown! 4c4762a1bSJed Brown 5c4762a1bSJed Brownprogram main 6c4762a1bSJed Brown#include <petsc/finclude/petsc.h> 7c4762a1bSJed Brown use petsc 8c4762a1bSJed Brown implicit none 9c4762a1bSJed Brown 10c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 11c4762a1bSJed Brown! Variable declarations 12c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 13c4762a1bSJed Brown! 14c4762a1bSJed Brown! Variables: 15c4762a1bSJed Brown! snes - nonlinear solver 16c4762a1bSJed Brown! ksp - linear solver 17c4762a1bSJed Brown! pc - preconditioner context 18c4762a1bSJed Brown! ksp - Krylov subspace method context 19c4762a1bSJed Brown! x, r - solution, residual vectors 20c4762a1bSJed Brown! J - Jacobian matrix 21c4762a1bSJed Brown! its - iterations for convergence 22c4762a1bSJed Brown! 23c4762a1bSJed Brown SNES snes 24c4762a1bSJed Brown PC pc 25c4762a1bSJed Brown KSP ksp 26c4762a1bSJed Brown Vec x, r 27c4762a1bSJed Brown Mat J 28c4762a1bSJed Brown SNESLineSearch linesearch 29c4762a1bSJed Brown PetscErrorCode ierr 30c4762a1bSJed Brown PetscInt its, i2, i20 31c4762a1bSJed Brown PetscMPIInt size, rank 32c4762a1bSJed Brown PetscScalar pfive 33c4762a1bSJed Brown PetscReal tol 34c4762a1bSJed Brown PetscBool setls 35ce78bad3SBarry Smith PetscReal, pointer :: rhistory(:) 36ce78bad3SBarry Smith PetscInt, pointer :: itshistory(:) 37ce78bad3SBarry Smith PetscInt nhistory 38956f8c0dSBarry Smith#if defined(PETSC_USE_LOG) 39c4762a1bSJed Brown PetscViewer viewer 40956f8c0dSBarry Smith#endif 41c4762a1bSJed Brown double precision threshold, oldthreshold 42c4762a1bSJed Brown 43c4762a1bSJed Brown! Note: Any user-defined Fortran routines (such as FormJacobian) 44c4762a1bSJed Brown! MUST be declared as external. 45c4762a1bSJed Brown 46c4762a1bSJed Brown external FormFunction, FormJacobian, MyLineSearch 47c4762a1bSJed Brown 48c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 49c4762a1bSJed Brown! Beginning of program 50c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 51c4762a1bSJed Brown 52d8606c27SBarry Smith PetscCallA(PetscInitialize(ierr)) 53d8606c27SBarry Smith PetscCallA(PetscLogNestedBegin(ierr)) 54c4762a1bSJed Brown threshold = 1.0 55d8606c27SBarry Smith PetscCallA(PetscLogSetThreshold(threshold, oldthreshold, ierr)) 56d8606c27SBarry Smith PetscCallMPIA(MPI_Comm_size(PETSC_COMM_WORLD, size, ierr)) 57d8606c27SBarry Smith PetscCallMPIA(MPI_Comm_rank(PETSC_COMM_WORLD, rank, ierr)) 58*4820e4eaSBarry Smith PetscCheckA(size == 1, PETSC_COMM_SELF, PETSC_ERR_WRONG_MPI_SIZE, 'Uniprocessor example') 59c4762a1bSJed Brown 60c4762a1bSJed Brown i2 = 2 61c4762a1bSJed Brown i20 = 20 62c4762a1bSJed Brown! - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - 63c4762a1bSJed Brown! Create nonlinear solver context 64c4762a1bSJed Brown! - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - 65c4762a1bSJed Brown 66d8606c27SBarry Smith PetscCallA(SNESCreate(PETSC_COMM_WORLD, snes, ierr)) 67c4762a1bSJed Brown 68ce78bad3SBarry Smith PetscCallA(SNESSetConvergenceHistory(snes, PETSC_NULL_REAL_ARRAY, PETSC_NULL_INTEGER_ARRAY, PETSC_DECIDE, PETSC_FALSE, ierr)) 69ce78bad3SBarry Smith 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 106fb842aefSJose E. Roman PetscCallA(KSPSetTolerances(ksp, tol, PETSC_CURRENT_REAL, PETSC_CURRENT_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)) 1219bcc50f1SBarry Smith PetscCallA(SNESLineSearchShellSetApply(linesearch, MyLineSearch, 0, ierr)) 122c4762a1bSJed Brown end if 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 137ce78bad3SBarry Smith PetscCallA(SNESGetConvergenceHistory(snes, rhistory, itshistory, nhistory, ierr)) 138ce78bad3SBarry Smith PetscCallA(SNESRestoreConvergenceHistory(snes, rhistory, itshistory, nhistory, ierr)) 139ce78bad3SBarry Smith 14091f3e32bSBarry Smith! View solver converged reason; we could instead use the option -snes_converged_reason 141d8606c27SBarry Smith PetscCallA(SNESConvergedReasonView(snes, PETSC_VIEWER_STDOUT_WORLD, ierr)) 14291f3e32bSBarry Smith 143d8606c27SBarry Smith PetscCallA(SNESGetIterationNumber(snes, its, ierr)) 144*4820e4eaSBarry Smith if (rank == 0) then 145c4762a1bSJed Brown write (6, 100) its 146c4762a1bSJed Brown end if 147c4762a1bSJed Brown100 format('Number of SNES iterations = ', i5) 148c4762a1bSJed Brown 149c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 150c4762a1bSJed Brown! Free work space. All PETSc objects should be destroyed when they 151c4762a1bSJed Brown! are no longer needed. 152c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 153c4762a1bSJed Brown 154d8606c27SBarry Smith PetscCallA(VecDestroy(x, ierr)) 155d8606c27SBarry Smith PetscCallA(VecDestroy(r, ierr)) 156d8606c27SBarry Smith PetscCallA(MatDestroy(J, ierr)) 157d8606c27SBarry Smith PetscCallA(SNESDestroy(snes, ierr)) 158956f8c0dSBarry Smith#if defined(PETSC_USE_LOG) 159d8606c27SBarry Smith PetscCallA(PetscViewerASCIIOpen(PETSC_COMM_WORLD, 'filename.xml', viewer, ierr)) 160d8606c27SBarry Smith PetscCallA(PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_XML, ierr)) 161d8606c27SBarry Smith PetscCallA(PetscLogView(viewer, ierr)) 162d8606c27SBarry Smith PetscCallA(PetscViewerDestroy(viewer, ierr)) 163956f8c0dSBarry Smith#endif 164d8606c27SBarry Smith PetscCallA(PetscFinalize(ierr)) 165c4762a1bSJed Brownend 166c4762a1bSJed Brown! 167c4762a1bSJed Brown! ------------------------------------------------------------------------ 168c4762a1bSJed Brown! 169c4762a1bSJed Brown! FormFunction - Evaluates nonlinear function, F(x). 170c4762a1bSJed Brown! 171c4762a1bSJed Brown! Input Parameters: 172c4762a1bSJed Brown! snes - the SNES context 173c4762a1bSJed Brown! x - input vector 174c4762a1bSJed Brown! dummy - optional user-defined context (not used here) 175c4762a1bSJed Brown! 176c4762a1bSJed Brown! Output Parameter: 177c4762a1bSJed Brown! f - function vector 178c4762a1bSJed Brown! 179c4762a1bSJed Brownsubroutine FormFunction(snes, x, f, dummy, ierr) 180ce78bad3SBarry Smith use petscvec 181ce78bad3SBarry Smith use petscsnesdef 182c4762a1bSJed Brown implicit none 183c4762a1bSJed Brown 184c4762a1bSJed Brown SNES snes 185c4762a1bSJed Brown Vec x, f 186c4762a1bSJed Brown PetscErrorCode ierr 187c4762a1bSJed Brown integer dummy(*) 188c4762a1bSJed Brown 189c4762a1bSJed Brown! Declarations for use with local arrays 19042ce371bSBarry Smith PetscScalar, pointer :: lx_v(:), lf_v(:) 191c4762a1bSJed Brown 192c4762a1bSJed Brown! Get pointers to vector data. 193ce78bad3SBarry Smith! - VecGetArray() returns a pointer to the data array. 194ce78bad3SBarry Smith! - You MUST call VecRestoreArray() when you no longer need access to 195c4762a1bSJed Brown! the array. 196c4762a1bSJed Brown 197ce78bad3SBarry Smith PetscCall(VecGetArrayRead(x, lx_v, ierr)) 198ce78bad3SBarry Smith PetscCall(VecGetArray(f, lf_v, ierr)) 199c4762a1bSJed Brown 200c4762a1bSJed Brown! Compute function 201c4762a1bSJed Brown 20242ce371bSBarry Smith lf_v(1) = lx_v(1)*lx_v(1) + lx_v(1)*lx_v(2) - 3.0 20342ce371bSBarry Smith lf_v(2) = lx_v(1)*lx_v(2) + lx_v(2)*lx_v(2) - 6.0 204c4762a1bSJed Brown 205c4762a1bSJed Brown! Restore vectors 206c4762a1bSJed Brown 207ce78bad3SBarry Smith PetscCall(VecRestoreArrayRead(x, lx_v, ierr)) 208ce78bad3SBarry Smith PetscCall(VecRestoreArray(f, lf_v, ierr)) 209c4762a1bSJed Brown 210c4762a1bSJed Brownend 211c4762a1bSJed Brown 212c4762a1bSJed Brown! --------------------------------------------------------------------- 213c4762a1bSJed Brown! 214c4762a1bSJed Brown! FormJacobian - Evaluates Jacobian matrix. 215c4762a1bSJed Brown! 216c4762a1bSJed Brown! Input Parameters: 217c4762a1bSJed Brown! snes - the SNES context 218c4762a1bSJed Brown! x - input vector 219c4762a1bSJed Brown! dummy - optional user-defined context (not used here) 220c4762a1bSJed Brown! 221c4762a1bSJed Brown! Output Parameters: 222c4762a1bSJed Brown! A - Jacobian matrix 2237addb90fSBarry Smith! B - optionally different matrix used to construct the preconditioner 224c4762a1bSJed Brown! 225c4762a1bSJed Brownsubroutine FormJacobian(snes, X, jac, B, dummy, ierr) 226ce78bad3SBarry Smith use petscvec 227ce78bad3SBarry Smith use petscmat 228ce78bad3SBarry Smith use petscsnesdef 229c4762a1bSJed Brown implicit none 230c4762a1bSJed Brown 231c4762a1bSJed Brown SNES snes 232c4762a1bSJed Brown Vec X 233c4762a1bSJed Brown Mat jac, B 234c4762a1bSJed Brown PetscScalar A(4) 235c4762a1bSJed Brown PetscErrorCode ierr 236c4762a1bSJed Brown PetscInt idx(2), i2 237c4762a1bSJed Brown integer dummy(*) 238c4762a1bSJed Brown 239c4762a1bSJed Brown! Declarations for use with local arrays 240c4762a1bSJed Brown 24142ce371bSBarry Smith PetscScalar, pointer :: lx_v(:) 242c4762a1bSJed Brown 243c4762a1bSJed Brown! Get pointer to vector data 244c4762a1bSJed Brown 245c4762a1bSJed Brown i2 = 2 246ce78bad3SBarry Smith PetscCall(VecGetArrayRead(x, lx_v, ierr)) 247c4762a1bSJed Brown 248c4762a1bSJed Brown! Compute Jacobian entries and insert into matrix. 249c4762a1bSJed Brown! - Since this is such a small problem, we set all entries for 250c4762a1bSJed Brown! the matrix at once. 251c4762a1bSJed Brown! - Note that MatSetValues() uses 0-based row and column numbers 252c4762a1bSJed Brown! in Fortran as well as in C (as set here in the array idx). 253c4762a1bSJed Brown 254c4762a1bSJed Brown idx(1) = 0 255c4762a1bSJed Brown idx(2) = 1 25642ce371bSBarry Smith A(1) = 2.0*lx_v(1) + lx_v(2) 25742ce371bSBarry Smith A(2) = lx_v(1) 25842ce371bSBarry Smith A(3) = lx_v(2) 25942ce371bSBarry Smith A(4) = lx_v(1) + 2.0*lx_v(2) 260d8606c27SBarry Smith PetscCall(MatSetValues(B, i2, idx, i2, idx, A, INSERT_VALUES, ierr)) 261c4762a1bSJed Brown 262c4762a1bSJed Brown! Restore vector 263c4762a1bSJed Brown 264ce78bad3SBarry Smith PetscCall(VecRestoreArrayRead(x, lx_v, ierr)) 265c4762a1bSJed Brown 266c4762a1bSJed Brown! Assemble matrix 267c4762a1bSJed Brown 268d8606c27SBarry Smith PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY, ierr)) 269d8606c27SBarry Smith PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY, ierr)) 270*4820e4eaSBarry Smith if (B /= jac) then 271d8606c27SBarry Smith PetscCall(MatAssemblyBegin(jac, MAT_FINAL_ASSEMBLY, ierr)) 272d8606c27SBarry Smith PetscCall(MatAssemblyEnd(jac, MAT_FINAL_ASSEMBLY, ierr)) 273c4762a1bSJed Brown end if 274c4762a1bSJed Brown 275c4762a1bSJed Brownend 276c4762a1bSJed Brown 277c4762a1bSJed Brownsubroutine MyLineSearch(linesearch, lctx, ierr) 278c4762a1bSJed Brown use petscsnes 279ce78bad3SBarry Smith use petscvec 280c4762a1bSJed Brown implicit none 281c4762a1bSJed Brown 282c4762a1bSJed Brown SNESLineSearch linesearch 283c4762a1bSJed Brown SNES snes 284c4762a1bSJed Brown integer lctx 285c4762a1bSJed Brown Vec x, f, g, y, w 286c4762a1bSJed Brown PetscReal ynorm, gnorm, xnorm 287c4762a1bSJed Brown PetscErrorCode ierr 288c4762a1bSJed Brown 289c4762a1bSJed Brown PetscScalar mone 290c4762a1bSJed Brown 291c4762a1bSJed Brown mone = -1.0 292d8606c27SBarry Smith PetscCall(SNESLineSearchGetSNES(linesearch, snes, ierr)) 293d8606c27SBarry Smith PetscCall(SNESLineSearchGetVecs(linesearch, x, f, y, w, g, ierr)) 294d8606c27SBarry Smith PetscCall(VecNorm(y, NORM_2, ynorm, ierr)) 295d8606c27SBarry Smith PetscCall(VecAXPY(x, mone, y, ierr)) 296d8606c27SBarry Smith PetscCall(SNESComputeFunction(snes, x, f, ierr)) 297d8606c27SBarry Smith PetscCall(VecNorm(f, NORM_2, gnorm, ierr)) 298d8606c27SBarry Smith PetscCall(VecNorm(x, NORM_2, xnorm, ierr)) 299d8606c27SBarry Smith PetscCall(VecNorm(y, NORM_2, ynorm, ierr)) 300d8606c27SBarry Smith PetscCall(SNESLineSearchSetNorms(linesearch, xnorm, gnorm, ynorm, ierr)) 301c4762a1bSJed Brownend 302c4762a1bSJed Brown 303c4762a1bSJed Brown!/*TEST 304c4762a1bSJed Brown! 305c4762a1bSJed Brown! test: 306c4762a1bSJed Brown! args: -ksp_gmres_cgs_refinement_type refine_always -snes_monitor_short 307c4762a1bSJed Brown! requires: !single 308c4762a1bSJed Brown! 309c4762a1bSJed Brown!TEST*/ 310