xref: /petsc/src/snes/tutorials/ex1f.F90 (revision 7addb90f52a7936ba144cdab1bb2cc37152af090)
1c4762a1bSJed Brown!
2c4762a1bSJed Brown!  Description: Uses the Newton method to solve a two-variable system.
3c4762a1bSJed Brown!
4c4762a1bSJed Brown
5c4762a1bSJed Brown      program 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))
58dcb3e689SBarry Smith      PetscCheckA(size .eq. 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      endif
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))
144c4762a1bSJed Brown      if (rank .eq. 0) then
145c4762a1bSJed Brown         write(6,100) its
146c4762a1bSJed Brown      endif
147c4762a1bSJed Brown  100 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 Brown      end
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 Brown      subroutine 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 Brown      end
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
223*7addb90fSBarry Smith!  B - optionally different matrix used to construct the preconditioner
224c4762a1bSJed Brown!
225c4762a1bSJed Brown      subroutine 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))
270c4762a1bSJed Brown      if (B .ne. jac) then
271d8606c27SBarry Smith        PetscCall(MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY,ierr))
272d8606c27SBarry Smith        PetscCall(MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY,ierr))
273c4762a1bSJed Brown      endif
274c4762a1bSJed Brown
275c4762a1bSJed Brown      end
276c4762a1bSJed Brown
277c4762a1bSJed Brown      subroutine 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 Brown      end
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