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