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