xref: /petsc/src/snes/tutorials/ex1f.F90 (revision d8606c274c09e255c003062beb17b1be973467bc)
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!                   Macro definitions
48c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
49c4762a1bSJed Brown!
50c4762a1bSJed Brown!  Macros to make clearer the process of setting values in vectors and
51c4762a1bSJed Brown!  getting values from vectors.  These vectors are used in the routines
52c4762a1bSJed Brown!  FormFunction() and FormJacobian().
53c4762a1bSJed Brown!   - The element lx_a(ib) is element ib in the vector x
54c4762a1bSJed Brown!
55c4762a1bSJed Brown#define lx_a(ib) lx_v(lx_i + (ib))
56c4762a1bSJed Brown#define lf_a(ib) lf_v(lf_i + (ib))
57c4762a1bSJed Brown!
58c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
59c4762a1bSJed Brown!                 Beginning of program
60c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
61c4762a1bSJed Brown
62*d8606c27SBarry Smith      PetscCallA(PetscInitialize(ierr))
63*d8606c27SBarry Smith      PetscCallA(PetscLogNestedBegin(ierr))
64c4762a1bSJed Brown      threshold = 1.0
65*d8606c27SBarry Smith      PetscCallA(PetscLogSetThreshold(threshold,oldthreshold,ierr))
66c4762a1bSJed Brown! dummy test of logging a reduction
67956f8c0dSBarry Smith#if defined(PETSC_USE_LOG)
68c4762a1bSJed Brown      ierr = PetscAReduce()
69956f8c0dSBarry Smith#endif
70*d8606c27SBarry Smith      PetscCallMPIA(MPI_Comm_size(PETSC_COMM_WORLD,size,ierr))
71*d8606c27SBarry Smith      PetscCallMPIA(MPI_Comm_rank(PETSC_COMM_WORLD,rank,ierr))
72c4762a1bSJed Brown      if (size .ne. 1) then; SETERRA(PETSC_COMM_SELF,PETSC_ERR_WRONG_MPI_SIZE,'Uniprocessor example'); endif
73c4762a1bSJed Brown
74c4762a1bSJed Brown      i2  = 2
75c4762a1bSJed Brown      i20 = 20
76c4762a1bSJed Brown! - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - -
77c4762a1bSJed Brown!  Create nonlinear solver context
78c4762a1bSJed Brown! - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - -
79c4762a1bSJed Brown
80*d8606c27SBarry Smith      PetscCallA(SNESCreate(PETSC_COMM_WORLD,snes,ierr))
81c4762a1bSJed Brown
82c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
83c4762a1bSJed Brown!  Create matrix and vector data structures; set corresponding routines
84c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
85c4762a1bSJed Brown
86c4762a1bSJed Brown!  Create vectors for solution and nonlinear function
87c4762a1bSJed Brown
88*d8606c27SBarry Smith      PetscCallA(VecCreateSeq(PETSC_COMM_SELF,i2,x,ierr))
89*d8606c27SBarry Smith      PetscCallA(VecDuplicate(x,r,ierr))
90c4762a1bSJed Brown
91c4762a1bSJed Brown!  Create Jacobian matrix data structure
92c4762a1bSJed Brown
93*d8606c27SBarry Smith      PetscCallA(MatCreate(PETSC_COMM_SELF,J,ierr))
94*d8606c27SBarry Smith      PetscCallA(MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,i2,i2,ierr))
95*d8606c27SBarry Smith      PetscCallA(MatSetFromOptions(J,ierr))
96*d8606c27SBarry Smith      PetscCallA(MatSetUp(J,ierr))
97c4762a1bSJed Brown
98c4762a1bSJed Brown!  Set function evaluation routine and vector
99c4762a1bSJed Brown
100*d8606c27SBarry Smith      PetscCallA(SNESSetFunction(snes,r,FormFunction,0,ierr))
101c4762a1bSJed Brown
102c4762a1bSJed Brown!  Set Jacobian matrix data structure and Jacobian evaluation routine
103c4762a1bSJed Brown
104*d8606c27SBarry Smith      PetscCallA(SNESSetJacobian(snes,J,J,FormJacobian,0,ierr))
105c4762a1bSJed Brown
106c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
107c4762a1bSJed Brown!  Customize nonlinear solver; set runtime options
108c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
109c4762a1bSJed Brown
110c4762a1bSJed Brown!  Set linear solver defaults for this problem. By extracting the
111c4762a1bSJed Brown!  KSP, KSP, and PC contexts from the SNES context, we can then
112c4762a1bSJed Brown!  directly call any KSP, KSP, and PC routines to set various options.
113c4762a1bSJed Brown
114*d8606c27SBarry Smith      PetscCallA(SNESGetKSP(snes,ksp,ierr))
115*d8606c27SBarry Smith      PetscCallA(KSPGetPC(ksp,pc,ierr))
116*d8606c27SBarry Smith      PetscCallA(PCSetType(pc,PCNONE,ierr))
117c4762a1bSJed Brown      tol = 1.e-4
118*d8606c27SBarry Smith      PetscCallA(KSPSetTolerances(ksp,tol,PETSC_DEFAULT_REAL,PETSC_DEFAULT_REAL,i20,ierr))
119c4762a1bSJed Brown
120c4762a1bSJed Brown!  Set SNES/KSP/KSP/PC runtime options, e.g.,
121c4762a1bSJed Brown!      -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc>
122c4762a1bSJed Brown!  These options will override those specified above as long as
123c4762a1bSJed Brown!  SNESSetFromOptions() is called _after_ any other customization
124c4762a1bSJed Brown!  routines.
125c4762a1bSJed Brown
126*d8606c27SBarry Smith      PetscCallA(SNESSetFromOptions(snes,ierr))
127c4762a1bSJed Brown
128*d8606c27SBarry Smith      PetscCallA(PetscOptionsHasName(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-setls',setls,ierr))
129c4762a1bSJed Brown
130c4762a1bSJed Brown      if (setls) then
131*d8606c27SBarry Smith        PetscCallA(SNESGetLineSearch(snes, linesearch, ierr))
132*d8606c27SBarry Smith        PetscCallA(SNESLineSearchSetType(linesearch, 'shell', ierr))
133*d8606c27SBarry Smith        PetscCallA(SNESLineSearchShellSetUserFunc(linesearch, MyLineSearch,0,ierr))
134c4762a1bSJed Brown      endif
135c4762a1bSJed Brown
136c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
137c4762a1bSJed Brown!  Evaluate initial guess; then solve nonlinear system
138c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
139c4762a1bSJed Brown
140c4762a1bSJed Brown!  Note: The user should initialize the vector, x, with the initial guess
141c4762a1bSJed Brown!  for the nonlinear solver prior to calling SNESSolve().  In particular,
142c4762a1bSJed Brown!  to employ an initial guess of zero, the user should explicitly set
143c4762a1bSJed Brown!  this vector to zero by calling VecSet().
144c4762a1bSJed Brown
145c4762a1bSJed Brown      pfive = 0.5
146*d8606c27SBarry Smith      PetscCallA(VecSet(x,pfive,ierr))
147*d8606c27SBarry Smith      PetscCallA(SNESSolve(snes,PETSC_NULL_VEC,x,ierr))
14891f3e32bSBarry Smith
14991f3e32bSBarry Smith!  View solver converged reason; we could instead use the option -snes_converged_reason
150*d8606c27SBarry Smith      PetscCallA(SNESConvergedReasonView(snes,PETSC_VIEWER_STDOUT_WORLD,ierr))
15191f3e32bSBarry Smith
152*d8606c27SBarry Smith      PetscCallA(SNESGetIterationNumber(snes,its,ierr))
153c4762a1bSJed Brown      if (rank .eq. 0) then
154c4762a1bSJed Brown         write(6,100) its
155c4762a1bSJed Brown      endif
156c4762a1bSJed Brown  100 format('Number of SNES iterations = ',i5)
157c4762a1bSJed Brown
158c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
159c4762a1bSJed Brown!  Free work space.  All PETSc objects should be destroyed when they
160c4762a1bSJed Brown!  are no longer needed.
161c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
162c4762a1bSJed Brown
163*d8606c27SBarry Smith      PetscCallA(VecDestroy(x,ierr))
164*d8606c27SBarry Smith      PetscCallA(VecDestroy(r,ierr))
165*d8606c27SBarry Smith      PetscCallA(MatDestroy(J,ierr))
166*d8606c27SBarry Smith      PetscCallA(SNESDestroy(snes,ierr))
167956f8c0dSBarry Smith#if defined(PETSC_USE_LOG)
168*d8606c27SBarry Smith      PetscCallA(PetscViewerASCIIOpen(PETSC_COMM_WORLD,'filename.xml',viewer,ierr))
169*d8606c27SBarry Smith      PetscCallA(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_XML,ierr))
170*d8606c27SBarry Smith      PetscCallA(PetscLogView(viewer,ierr))
171*d8606c27SBarry Smith      PetscCallA(PetscViewerDestroy(viewer,ierr))
172956f8c0dSBarry Smith#endif
173*d8606c27SBarry Smith      PetscCallA(PetscFinalize(ierr))
174c4762a1bSJed Brown      end
175c4762a1bSJed Brown!
176c4762a1bSJed Brown! ------------------------------------------------------------------------
177c4762a1bSJed Brown!
178c4762a1bSJed Brown!  FormFunction - Evaluates nonlinear function, F(x).
179c4762a1bSJed Brown!
180c4762a1bSJed Brown!  Input Parameters:
181c4762a1bSJed Brown!  snes - the SNES context
182c4762a1bSJed Brown!  x - input vector
183c4762a1bSJed Brown!  dummy - optional user-defined context (not used here)
184c4762a1bSJed Brown!
185c4762a1bSJed Brown!  Output Parameter:
186c4762a1bSJed Brown!  f - function vector
187c4762a1bSJed Brown!
188c4762a1bSJed Brown      subroutine FormFunction(snes,x,f,dummy,ierr)
189c4762a1bSJed Brown      use petscsnes
190c4762a1bSJed Brown      implicit none
191c4762a1bSJed Brown
192c4762a1bSJed Brown      SNES     snes
193c4762a1bSJed Brown      Vec      x,f
194c4762a1bSJed Brown      PetscErrorCode ierr
195c4762a1bSJed Brown      integer dummy(*)
196c4762a1bSJed Brown
197c4762a1bSJed Brown!  Declarations for use with local arrays
198c4762a1bSJed Brown
199c4762a1bSJed Brown      PetscScalar  lx_v(2),lf_v(2)
200c4762a1bSJed Brown      PetscOffset  lx_i,lf_i
201c4762a1bSJed Brown
202c4762a1bSJed Brown!  Get pointers to vector data.
203c4762a1bSJed Brown!    - For default PETSc vectors, VecGetArray() returns a pointer to
204c4762a1bSJed Brown!      the data array.  Otherwise, the routine is implementation dependent.
205c4762a1bSJed Brown!    - You MUST call VecRestoreArray() when you no longer need access to
206c4762a1bSJed Brown!      the array.
207c4762a1bSJed Brown!    - Note that the Fortran interface to VecGetArray() differs from the
208c4762a1bSJed Brown!      C version.  See the Fortran chapter of the users manual for details.
209c4762a1bSJed Brown
210*d8606c27SBarry Smith      PetscCall(VecGetArrayRead(x,lx_v,lx_i,ierr))
211*d8606c27SBarry Smith      PetscCall(VecGetArray(f,lf_v,lf_i,ierr))
212c4762a1bSJed Brown
213c4762a1bSJed Brown!  Compute function
214c4762a1bSJed Brown
215*d8606c27SBarry Smith      lf_a(1) = lx_a(1)*lx_a(1) + lx_a(1)*lx_a(2) - 3.0
216*d8606c27SBarry Smith      lf_a(2) = lx_a(1)*lx_a(2) + lx_a(2)*lx_a(2) - 6.0
217c4762a1bSJed Brown
218c4762a1bSJed Brown!  Restore vectors
219c4762a1bSJed Brown
220*d8606c27SBarry Smith      PetscCall(VecRestoreArrayRead(x,lx_v,lx_i,ierr))
221*d8606c27SBarry Smith      PetscCall(VecRestoreArray(f,lf_v,lf_i,ierr))
222c4762a1bSJed Brown
223c4762a1bSJed Brown      return
224c4762a1bSJed Brown      end
225c4762a1bSJed Brown
226c4762a1bSJed Brown! ---------------------------------------------------------------------
227c4762a1bSJed Brown!
228c4762a1bSJed Brown!  FormJacobian - Evaluates Jacobian matrix.
229c4762a1bSJed Brown!
230c4762a1bSJed Brown!  Input Parameters:
231c4762a1bSJed Brown!  snes - the SNES context
232c4762a1bSJed Brown!  x - input vector
233c4762a1bSJed Brown!  dummy - optional user-defined context (not used here)
234c4762a1bSJed Brown!
235c4762a1bSJed Brown!  Output Parameters:
236c4762a1bSJed Brown!  A - Jacobian matrix
237c4762a1bSJed Brown!  B - optionally different preconditioning matrix
238c4762a1bSJed Brown!
239c4762a1bSJed Brown      subroutine FormJacobian(snes,X,jac,B,dummy,ierr)
240c4762a1bSJed Brown      use petscsnes
241c4762a1bSJed Brown      implicit none
242c4762a1bSJed Brown
243c4762a1bSJed Brown      SNES         snes
244c4762a1bSJed Brown      Vec          X
245c4762a1bSJed Brown      Mat          jac,B
246c4762a1bSJed Brown      PetscScalar  A(4)
247c4762a1bSJed Brown      PetscErrorCode ierr
248c4762a1bSJed Brown      PetscInt idx(2),i2
249c4762a1bSJed Brown      integer dummy(*)
250c4762a1bSJed Brown
251c4762a1bSJed Brown!  Declarations for use with local arrays
252c4762a1bSJed Brown
253c4762a1bSJed Brown      PetscScalar lx_v(2)
254c4762a1bSJed Brown      PetscOffset lx_i
255c4762a1bSJed Brown
256c4762a1bSJed Brown!  Get pointer to vector data
257c4762a1bSJed Brown
258c4762a1bSJed Brown      i2 = 2
259*d8606c27SBarry Smith      PetscCall(VecGetArrayRead(x,lx_v,lx_i,ierr))
260c4762a1bSJed Brown
261c4762a1bSJed Brown!  Compute Jacobian entries and insert into matrix.
262c4762a1bSJed Brown!   - Since this is such a small problem, we set all entries for
263c4762a1bSJed Brown!     the matrix at once.
264c4762a1bSJed Brown!   - Note that MatSetValues() uses 0-based row and column numbers
265c4762a1bSJed Brown!     in Fortran as well as in C (as set here in the array idx).
266c4762a1bSJed Brown
267c4762a1bSJed Brown      idx(1) = 0
268c4762a1bSJed Brown      idx(2) = 1
269c4762a1bSJed Brown      A(1) = 2.0*lx_a(1) + lx_a(2)
270c4762a1bSJed Brown      A(2) = lx_a(1)
271c4762a1bSJed Brown      A(3) = lx_a(2)
272c4762a1bSJed Brown      A(4) = lx_a(1) + 2.0*lx_a(2)
273*d8606c27SBarry Smith      PetscCall(MatSetValues(B,i2,idx,i2,idx,A,INSERT_VALUES,ierr))
274c4762a1bSJed Brown
275c4762a1bSJed Brown!  Restore vector
276c4762a1bSJed Brown
277*d8606c27SBarry Smith      PetscCall(VecRestoreArrayRead(x,lx_v,lx_i,ierr))
278c4762a1bSJed Brown
279c4762a1bSJed Brown!  Assemble matrix
280c4762a1bSJed Brown
281*d8606c27SBarry Smith      PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY,ierr))
282*d8606c27SBarry Smith      PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY,ierr))
283c4762a1bSJed Brown      if (B .ne. jac) then
284*d8606c27SBarry Smith        PetscCall(MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY,ierr))
285*d8606c27SBarry Smith        PetscCall(MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY,ierr))
286c4762a1bSJed Brown      endif
287c4762a1bSJed Brown
288c4762a1bSJed Brown      return
289c4762a1bSJed Brown      end
290c4762a1bSJed Brown
291c4762a1bSJed Brown      subroutine MyLineSearch(linesearch, lctx, ierr)
292c4762a1bSJed Brown      use petscsnes
293c4762a1bSJed Brown      implicit none
294c4762a1bSJed Brown
295c4762a1bSJed Brown      SNESLineSearch    linesearch
296c4762a1bSJed Brown      SNES              snes
297c4762a1bSJed Brown      integer           lctx
298c4762a1bSJed Brown      Vec               x, f,g, y, w
299c4762a1bSJed Brown      PetscReal         ynorm,gnorm,xnorm
300c4762a1bSJed Brown      PetscErrorCode    ierr
301c4762a1bSJed Brown
302c4762a1bSJed Brown      PetscScalar       mone
303c4762a1bSJed Brown
304c4762a1bSJed Brown      mone = -1.0
305*d8606c27SBarry Smith      PetscCall(SNESLineSearchGetSNES(linesearch, snes, ierr))
306*d8606c27SBarry Smith      PetscCall(SNESLineSearchGetVecs(linesearch, x, f, y, w, g, ierr))
307*d8606c27SBarry Smith      PetscCall(VecNorm(y,NORM_2,ynorm,ierr))
308*d8606c27SBarry Smith      PetscCall(VecAXPY(x,mone,y,ierr))
309*d8606c27SBarry Smith      PetscCall(SNESComputeFunction(snes,x,f,ierr))
310*d8606c27SBarry Smith      PetscCall(VecNorm(f,NORM_2,gnorm,ierr))
311*d8606c27SBarry Smith      PetscCall(VecNorm(x,NORM_2,xnorm,ierr))
312*d8606c27SBarry Smith      PetscCall(VecNorm(y,NORM_2,ynorm,ierr))
313*d8606c27SBarry Smith      PetscCall(SNESLineSearchSetNorms(linesearch, xnorm, gnorm, ynorm,ierr))
314c4762a1bSJed Brown      return
315c4762a1bSJed Brown      end
316c4762a1bSJed Brown
317c4762a1bSJed Brown!/*TEST
318c4762a1bSJed Brown!
319c4762a1bSJed Brown!   test:
320c4762a1bSJed Brown!      args: -ksp_gmres_cgs_refinement_type refine_always -snes_monitor_short
321c4762a1bSJed Brown!      requires: !single
322c4762a1bSJed Brown!
323c4762a1bSJed Brown!TEST*/
324