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*e7a95102SMartin Diehlmodule ex1f_mod 6*e7a95102SMartin Diehl use petscvec 7*e7a95102SMartin Diehl use petscsnesdef 8*e7a95102SMartin Diehl use petscvec 9*e7a95102SMartin Diehl use petscmat 10*e7a95102SMartin Diehl implicit none 11*e7a95102SMartin Diehl 12*e7a95102SMartin Diehlcontains 13*e7a95102SMartin Diehl! 14*e7a95102SMartin Diehl! ------------------------------------------------------------------------ 15*e7a95102SMartin Diehl! 16*e7a95102SMartin Diehl! FormFunction - Evaluates nonlinear function, F(x). 17*e7a95102SMartin Diehl! 18*e7a95102SMartin Diehl! Input Parameters: 19*e7a95102SMartin Diehl! snes - the SNES context 20*e7a95102SMartin Diehl! x - input vector 21*e7a95102SMartin Diehl! dummy - optional user-defined context (not used here) 22*e7a95102SMartin Diehl! 23*e7a95102SMartin Diehl! Output Parameter: 24*e7a95102SMartin Diehl! f - function vector 25*e7a95102SMartin Diehl! 26*e7a95102SMartin Diehl subroutine FormFunction(snes, x, f, dummy, ierr) 27*e7a95102SMartin Diehl SNES snes 28*e7a95102SMartin Diehl Vec x, f 29*e7a95102SMartin Diehl PetscErrorCode ierr 30*e7a95102SMartin Diehl integer dummy(*) 31*e7a95102SMartin Diehl 32*e7a95102SMartin Diehl! Declarations for use with local arrays 33*e7a95102SMartin Diehl PetscScalar, pointer :: lx_v(:), lf_v(:) 34*e7a95102SMartin Diehl 35*e7a95102SMartin Diehl! Get pointers to vector data. 36*e7a95102SMartin Diehl! - VecGetArray() returns a pointer to the data array. 37*e7a95102SMartin Diehl! - You MUST call VecRestoreArray() when you no longer need access to 38*e7a95102SMartin Diehl! the array. 39*e7a95102SMartin Diehl 40*e7a95102SMartin Diehl PetscCall(VecGetArrayRead(x, lx_v, ierr)) 41*e7a95102SMartin Diehl PetscCall(VecGetArray(f, lf_v, ierr)) 42*e7a95102SMartin Diehl 43*e7a95102SMartin Diehl! Compute function 44*e7a95102SMartin Diehl 45*e7a95102SMartin Diehl lf_v(1) = lx_v(1)*lx_v(1) + lx_v(1)*lx_v(2) - 3.0 46*e7a95102SMartin Diehl lf_v(2) = lx_v(1)*lx_v(2) + lx_v(2)*lx_v(2) - 6.0 47*e7a95102SMartin Diehl 48*e7a95102SMartin Diehl! Restore vectors 49*e7a95102SMartin Diehl 50*e7a95102SMartin Diehl PetscCall(VecRestoreArrayRead(x, lx_v, ierr)) 51*e7a95102SMartin Diehl PetscCall(VecRestoreArray(f, lf_v, ierr)) 52*e7a95102SMartin Diehl 53*e7a95102SMartin Diehl end 54*e7a95102SMartin Diehl 55*e7a95102SMartin Diehl! --------------------------------------------------------------------- 56*e7a95102SMartin Diehl! 57*e7a95102SMartin Diehl! FormJacobian - Evaluates Jacobian matrix. 58*e7a95102SMartin Diehl! 59*e7a95102SMartin Diehl! Input Parameters: 60*e7a95102SMartin Diehl! snes - the SNES context 61*e7a95102SMartin Diehl! x - input vector 62*e7a95102SMartin Diehl! dummy - optional user-defined context (not used here) 63*e7a95102SMartin Diehl! 64*e7a95102SMartin Diehl! Output Parameters: 65*e7a95102SMartin Diehl! A - Jacobian matrix 66*e7a95102SMartin Diehl! B - optionally different matrix used to construct the preconditioner 67*e7a95102SMartin Diehl! 68*e7a95102SMartin Diehl subroutine FormJacobian(snes, X, jac, B, dummy, ierr) 69*e7a95102SMartin Diehl 70*e7a95102SMartin Diehl SNES snes 71*e7a95102SMartin Diehl Vec X 72*e7a95102SMartin Diehl Mat jac, B 73*e7a95102SMartin Diehl PetscScalar A(4) 74*e7a95102SMartin Diehl PetscErrorCode ierr 75*e7a95102SMartin Diehl PetscInt idx(2), i2 76*e7a95102SMartin Diehl integer dummy(*) 77*e7a95102SMartin Diehl 78*e7a95102SMartin Diehl! Declarations for use with local arrays 79*e7a95102SMartin Diehl 80*e7a95102SMartin Diehl PetscScalar, pointer :: lx_v(:) 81*e7a95102SMartin Diehl 82*e7a95102SMartin Diehl! Get pointer to vector data 83*e7a95102SMartin Diehl 84*e7a95102SMartin Diehl i2 = 2 85*e7a95102SMartin Diehl PetscCall(VecGetArrayRead(x, lx_v, ierr)) 86*e7a95102SMartin Diehl 87*e7a95102SMartin Diehl! Compute Jacobian entries and insert into matrix. 88*e7a95102SMartin Diehl! - Since this is such a small problem, we set all entries for 89*e7a95102SMartin Diehl! the matrix at once. 90*e7a95102SMartin Diehl! - Note that MatSetValues() uses 0-based row and column numbers 91*e7a95102SMartin Diehl! in Fortran as well as in C (as set here in the array idx). 92*e7a95102SMartin Diehl 93*e7a95102SMartin Diehl idx(1) = 0 94*e7a95102SMartin Diehl idx(2) = 1 95*e7a95102SMartin Diehl A(1) = 2.0*lx_v(1) + lx_v(2) 96*e7a95102SMartin Diehl A(2) = lx_v(1) 97*e7a95102SMartin Diehl A(3) = lx_v(2) 98*e7a95102SMartin Diehl A(4) = lx_v(1) + 2.0*lx_v(2) 99*e7a95102SMartin Diehl PetscCall(MatSetValues(B, i2, idx, i2, idx, A, INSERT_VALUES, ierr)) 100*e7a95102SMartin Diehl 101*e7a95102SMartin Diehl! Restore vector 102*e7a95102SMartin Diehl 103*e7a95102SMartin Diehl PetscCall(VecRestoreArrayRead(x, lx_v, ierr)) 104*e7a95102SMartin Diehl 105*e7a95102SMartin Diehl! Assemble matrix 106*e7a95102SMartin Diehl 107*e7a95102SMartin Diehl PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY, ierr)) 108*e7a95102SMartin Diehl PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY, ierr)) 109*e7a95102SMartin Diehl if (B /= jac) then 110*e7a95102SMartin Diehl PetscCall(MatAssemblyBegin(jac, MAT_FINAL_ASSEMBLY, ierr)) 111*e7a95102SMartin Diehl PetscCall(MatAssemblyEnd(jac, MAT_FINAL_ASSEMBLY, ierr)) 112*e7a95102SMartin Diehl end if 113*e7a95102SMartin Diehl 114*e7a95102SMartin Diehl end 115*e7a95102SMartin Diehl 116*e7a95102SMartin Diehl subroutine MyLineSearch(linesearch, lctx, ierr) 117*e7a95102SMartin Diehl 118*e7a95102SMartin Diehl SNESLineSearch linesearch 119*e7a95102SMartin Diehl SNES snes 120*e7a95102SMartin Diehl integer lctx 121*e7a95102SMartin Diehl Vec x, f, g, y, w 122*e7a95102SMartin Diehl PetscReal ynorm, gnorm, xnorm 123*e7a95102SMartin Diehl PetscErrorCode ierr 124*e7a95102SMartin Diehl 125*e7a95102SMartin Diehl PetscScalar mone 126*e7a95102SMartin Diehl 127*e7a95102SMartin Diehl mone = -1.0 128*e7a95102SMartin Diehl PetscCall(SNESLineSearchGetSNES(linesearch, snes, ierr)) 129*e7a95102SMartin Diehl PetscCall(SNESLineSearchGetVecs(linesearch, x, f, y, w, g, ierr)) 130*e7a95102SMartin Diehl PetscCall(VecNorm(y, NORM_2, ynorm, ierr)) 131*e7a95102SMartin Diehl PetscCall(VecAXPY(x, mone, y, ierr)) 132*e7a95102SMartin Diehl PetscCall(SNESComputeFunction(snes, x, f, ierr)) 133*e7a95102SMartin Diehl PetscCall(VecNorm(f, NORM_2, gnorm, ierr)) 134*e7a95102SMartin Diehl PetscCall(VecNorm(x, NORM_2, xnorm, ierr)) 135*e7a95102SMartin Diehl PetscCall(VecNorm(y, NORM_2, ynorm, ierr)) 136*e7a95102SMartin Diehl PetscCall(SNESLineSearchSetNorms(linesearch, xnorm, gnorm, ynorm, ierr)) 137*e7a95102SMartin Diehl end 138*e7a95102SMartin Diehlend module 139*e7a95102SMartin Diehl 140c5e229c2SMartin Diehlprogram main 141c4762a1bSJed Brown use petsc 142*e7a95102SMartin Diehl use ex1f_mod 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