xref: /petsc/src/snes/tutorials/ex1f.F90 (revision fb842aef621b1ec3460f788b06270a63e1a90f33)
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
35956f8c0dSBarry Smith#if defined(PETSC_USE_LOG)
36c4762a1bSJed Brown      PetscViewer viewer
37956f8c0dSBarry Smith#endif
38c4762a1bSJed Brown      double precision threshold,oldthreshold
39c4762a1bSJed Brown
40c4762a1bSJed Brown!  Note: Any user-defined Fortran routines (such as FormJacobian)
41c4762a1bSJed Brown!  MUST be declared as external.
42c4762a1bSJed Brown
43c4762a1bSJed Brown      external FormFunction, FormJacobian, MyLineSearch
44c4762a1bSJed Brown
45c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
46c4762a1bSJed Brown!                 Beginning of program
47c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
48c4762a1bSJed Brown
49d8606c27SBarry Smith      PetscCallA(PetscInitialize(ierr))
50d8606c27SBarry Smith      PetscCallA(PetscLogNestedBegin(ierr))
51c4762a1bSJed Brown      threshold = 1.0
52d8606c27SBarry Smith      PetscCallA(PetscLogSetThreshold(threshold,oldthreshold,ierr))
53d8606c27SBarry Smith      PetscCallMPIA(MPI_Comm_size(PETSC_COMM_WORLD,size,ierr))
54d8606c27SBarry Smith      PetscCallMPIA(MPI_Comm_rank(PETSC_COMM_WORLD,rank,ierr))
55dcb3e689SBarry Smith      PetscCheckA(size .eq. 1,PETSC_COMM_SELF,PETSC_ERR_WRONG_MPI_SIZE,'Uniprocessor example')
56c4762a1bSJed Brown
57c4762a1bSJed Brown      i2  = 2
58c4762a1bSJed Brown      i20 = 20
59c4762a1bSJed Brown! - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - -
60c4762a1bSJed Brown!  Create nonlinear solver context
61c4762a1bSJed Brown! - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - -
62c4762a1bSJed Brown
63d8606c27SBarry Smith      PetscCallA(SNESCreate(PETSC_COMM_WORLD,snes,ierr))
64c4762a1bSJed Brown
65c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
66c4762a1bSJed Brown!  Create matrix and vector data structures; set corresponding routines
67c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
68c4762a1bSJed Brown
69c4762a1bSJed Brown!  Create vectors for solution and nonlinear function
70c4762a1bSJed Brown
71d8606c27SBarry Smith      PetscCallA(VecCreateSeq(PETSC_COMM_SELF,i2,x,ierr))
72d8606c27SBarry Smith      PetscCallA(VecDuplicate(x,r,ierr))
73c4762a1bSJed Brown
74c4762a1bSJed Brown!  Create Jacobian matrix data structure
75c4762a1bSJed Brown
76d8606c27SBarry Smith      PetscCallA(MatCreate(PETSC_COMM_SELF,J,ierr))
77d8606c27SBarry Smith      PetscCallA(MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,i2,i2,ierr))
78d8606c27SBarry Smith      PetscCallA(MatSetFromOptions(J,ierr))
79d8606c27SBarry Smith      PetscCallA(MatSetUp(J,ierr))
80c4762a1bSJed Brown
81c4762a1bSJed Brown!  Set function evaluation routine and vector
82c4762a1bSJed Brown
83d8606c27SBarry Smith      PetscCallA(SNESSetFunction(snes,r,FormFunction,0,ierr))
84c4762a1bSJed Brown
85c4762a1bSJed Brown!  Set Jacobian matrix data structure and Jacobian evaluation routine
86c4762a1bSJed Brown
87d8606c27SBarry Smith      PetscCallA(SNESSetJacobian(snes,J,J,FormJacobian,0,ierr))
88c4762a1bSJed Brown
89c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
90c4762a1bSJed Brown!  Customize nonlinear solver; set runtime options
91c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
92c4762a1bSJed Brown
93c4762a1bSJed Brown!  Set linear solver defaults for this problem. By extracting the
94c4762a1bSJed Brown!  KSP, KSP, and PC contexts from the SNES context, we can then
95c4762a1bSJed Brown!  directly call any KSP, KSP, and PC routines to set various options.
96c4762a1bSJed Brown
97d8606c27SBarry Smith      PetscCallA(SNESGetKSP(snes,ksp,ierr))
98d8606c27SBarry Smith      PetscCallA(KSPGetPC(ksp,pc,ierr))
99d8606c27SBarry Smith      PetscCallA(PCSetType(pc,PCNONE,ierr))
100c4762a1bSJed Brown      tol = 1.e-4
101*fb842aefSJose E. Roman      PetscCallA(KSPSetTolerances(ksp,tol,PETSC_CURRENT_REAL,PETSC_CURRENT_REAL,i20,ierr))
102c4762a1bSJed Brown
103c4762a1bSJed Brown!  Set SNES/KSP/KSP/PC runtime options, e.g.,
104c4762a1bSJed Brown!      -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc>
105c4762a1bSJed Brown!  These options will override those specified above as long as
106c4762a1bSJed Brown!  SNESSetFromOptions() is called _after_ any other customization
107c4762a1bSJed Brown!  routines.
108c4762a1bSJed Brown
109d8606c27SBarry Smith      PetscCallA(SNESSetFromOptions(snes,ierr))
110c4762a1bSJed Brown
111d8606c27SBarry Smith      PetscCallA(PetscOptionsHasName(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-setls',setls,ierr))
112c4762a1bSJed Brown
113c4762a1bSJed Brown      if (setls) then
114d8606c27SBarry Smith        PetscCallA(SNESGetLineSearch(snes, linesearch, ierr))
115d8606c27SBarry Smith        PetscCallA(SNESLineSearchSetType(linesearch, 'shell', ierr))
1169bcc50f1SBarry Smith        PetscCallA(SNESLineSearchShellSetApply(linesearch, MyLineSearch,0,ierr))
117c4762a1bSJed Brown      endif
118c4762a1bSJed Brown
119c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
120c4762a1bSJed Brown!  Evaluate initial guess; then solve nonlinear system
121c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
122c4762a1bSJed Brown
123c4762a1bSJed Brown!  Note: The user should initialize the vector, x, with the initial guess
124c4762a1bSJed Brown!  for the nonlinear solver prior to calling SNESSolve().  In particular,
125c4762a1bSJed Brown!  to employ an initial guess of zero, the user should explicitly set
126c4762a1bSJed Brown!  this vector to zero by calling VecSet().
127c4762a1bSJed Brown
128c4762a1bSJed Brown      pfive = 0.5
129d8606c27SBarry Smith      PetscCallA(VecSet(x,pfive,ierr))
130d8606c27SBarry Smith      PetscCallA(SNESSolve(snes,PETSC_NULL_VEC,x,ierr))
13191f3e32bSBarry Smith
13291f3e32bSBarry Smith!  View solver converged reason; we could instead use the option -snes_converged_reason
133d8606c27SBarry Smith      PetscCallA(SNESConvergedReasonView(snes,PETSC_VIEWER_STDOUT_WORLD,ierr))
13491f3e32bSBarry Smith
135d8606c27SBarry Smith      PetscCallA(SNESGetIterationNumber(snes,its,ierr))
136c4762a1bSJed Brown      if (rank .eq. 0) then
137c4762a1bSJed Brown         write(6,100) its
138c4762a1bSJed Brown      endif
139c4762a1bSJed Brown  100 format('Number of SNES iterations = ',i5)
140c4762a1bSJed Brown
141c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
142c4762a1bSJed Brown!  Free work space.  All PETSc objects should be destroyed when they
143c4762a1bSJed Brown!  are no longer needed.
144c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
145c4762a1bSJed Brown
146d8606c27SBarry Smith      PetscCallA(VecDestroy(x,ierr))
147d8606c27SBarry Smith      PetscCallA(VecDestroy(r,ierr))
148d8606c27SBarry Smith      PetscCallA(MatDestroy(J,ierr))
149d8606c27SBarry Smith      PetscCallA(SNESDestroy(snes,ierr))
150956f8c0dSBarry Smith#if defined(PETSC_USE_LOG)
151d8606c27SBarry Smith      PetscCallA(PetscViewerASCIIOpen(PETSC_COMM_WORLD,'filename.xml',viewer,ierr))
152d8606c27SBarry Smith      PetscCallA(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_XML,ierr))
153d8606c27SBarry Smith      PetscCallA(PetscLogView(viewer,ierr))
154d8606c27SBarry Smith      PetscCallA(PetscViewerDestroy(viewer,ierr))
155956f8c0dSBarry Smith#endif
156d8606c27SBarry Smith      PetscCallA(PetscFinalize(ierr))
157c4762a1bSJed Brown      end
158c4762a1bSJed Brown!
159c4762a1bSJed Brown! ------------------------------------------------------------------------
160c4762a1bSJed Brown!
161c4762a1bSJed Brown!  FormFunction - Evaluates nonlinear function, F(x).
162c4762a1bSJed Brown!
163c4762a1bSJed Brown!  Input Parameters:
164c4762a1bSJed Brown!  snes - the SNES context
165c4762a1bSJed Brown!  x - input vector
166c4762a1bSJed Brown!  dummy - optional user-defined context (not used here)
167c4762a1bSJed Brown!
168c4762a1bSJed Brown!  Output Parameter:
169c4762a1bSJed Brown!  f - function vector
170c4762a1bSJed Brown!
171c4762a1bSJed Brown      subroutine FormFunction(snes,x,f,dummy,ierr)
172c4762a1bSJed Brown      use petscsnes
173c4762a1bSJed Brown      implicit none
174c4762a1bSJed Brown
175c4762a1bSJed Brown      SNES     snes
176c4762a1bSJed Brown      Vec      x,f
177c4762a1bSJed Brown      PetscErrorCode ierr
178c4762a1bSJed Brown      integer dummy(*)
179c4762a1bSJed Brown
180c4762a1bSJed Brown!  Declarations for use with local arrays
18142ce371bSBarry Smith      PetscScalar,pointer :: lx_v(:),lf_v(:)
182c4762a1bSJed Brown
183c4762a1bSJed Brown!  Get pointers to vector data.
18442ce371bSBarry Smith!    - VecGetArrayF90() returns a pointer to the data array.
18542ce371bSBarry Smith!    - You MUST call VecRestoreArrayF90() when you no longer need access to
186c4762a1bSJed Brown!      the array.
187c4762a1bSJed Brown
18842ce371bSBarry Smith      PetscCall(VecGetArrayReadF90(x,lx_v,ierr))
18942ce371bSBarry Smith      PetscCall(VecGetArrayF90(f,lf_v,ierr))
190c4762a1bSJed Brown
191c4762a1bSJed Brown!  Compute function
192c4762a1bSJed Brown
19342ce371bSBarry Smith      lf_v(1) = lx_v(1)*lx_v(1) + lx_v(1)*lx_v(2) - 3.0
19442ce371bSBarry Smith      lf_v(2) = lx_v(1)*lx_v(2) + lx_v(2)*lx_v(2) - 6.0
195c4762a1bSJed Brown
196c4762a1bSJed Brown!  Restore vectors
197c4762a1bSJed Brown
19842ce371bSBarry Smith      PetscCall(VecRestoreArrayReadF90(x,lx_v,ierr))
19942ce371bSBarry Smith      PetscCall(VecRestoreArrayF90(f,lf_v,ierr))
200c4762a1bSJed Brown
201c4762a1bSJed Brown      end
202c4762a1bSJed Brown
203c4762a1bSJed Brown! ---------------------------------------------------------------------
204c4762a1bSJed Brown!
205c4762a1bSJed Brown!  FormJacobian - Evaluates Jacobian matrix.
206c4762a1bSJed Brown!
207c4762a1bSJed Brown!  Input Parameters:
208c4762a1bSJed Brown!  snes - the SNES context
209c4762a1bSJed Brown!  x - input vector
210c4762a1bSJed Brown!  dummy - optional user-defined context (not used here)
211c4762a1bSJed Brown!
212c4762a1bSJed Brown!  Output Parameters:
213c4762a1bSJed Brown!  A - Jacobian matrix
214c4762a1bSJed Brown!  B - optionally different preconditioning matrix
215c4762a1bSJed Brown!
216c4762a1bSJed Brown      subroutine FormJacobian(snes,X,jac,B,dummy,ierr)
217c4762a1bSJed Brown      use petscsnes
218c4762a1bSJed Brown      implicit none
219c4762a1bSJed Brown
220c4762a1bSJed Brown      SNES         snes
221c4762a1bSJed Brown      Vec          X
222c4762a1bSJed Brown      Mat          jac,B
223c4762a1bSJed Brown      PetscScalar  A(4)
224c4762a1bSJed Brown      PetscErrorCode ierr
225c4762a1bSJed Brown      PetscInt idx(2),i2
226c4762a1bSJed Brown      integer dummy(*)
227c4762a1bSJed Brown
228c4762a1bSJed Brown!  Declarations for use with local arrays
229c4762a1bSJed Brown
23042ce371bSBarry Smith      PetscScalar,pointer :: lx_v(:)
231c4762a1bSJed Brown
232c4762a1bSJed Brown!  Get pointer to vector data
233c4762a1bSJed Brown
234c4762a1bSJed Brown      i2 = 2
23542ce371bSBarry Smith      PetscCall(VecGetArrayReadF90(x,lx_v,ierr))
236c4762a1bSJed Brown
237c4762a1bSJed Brown!  Compute Jacobian entries and insert into matrix.
238c4762a1bSJed Brown!   - Since this is such a small problem, we set all entries for
239c4762a1bSJed Brown!     the matrix at once.
240c4762a1bSJed Brown!   - Note that MatSetValues() uses 0-based row and column numbers
241c4762a1bSJed Brown!     in Fortran as well as in C (as set here in the array idx).
242c4762a1bSJed Brown
243c4762a1bSJed Brown      idx(1) = 0
244c4762a1bSJed Brown      idx(2) = 1
24542ce371bSBarry Smith      A(1) = 2.0*lx_v(1) + lx_v(2)
24642ce371bSBarry Smith      A(2) = lx_v(1)
24742ce371bSBarry Smith      A(3) = lx_v(2)
24842ce371bSBarry Smith      A(4) = lx_v(1) + 2.0*lx_v(2)
249d8606c27SBarry Smith      PetscCall(MatSetValues(B,i2,idx,i2,idx,A,INSERT_VALUES,ierr))
250c4762a1bSJed Brown
251c4762a1bSJed Brown!  Restore vector
252c4762a1bSJed Brown
25342ce371bSBarry Smith      PetscCall(VecRestoreArrayReadF90(x,lx_v,ierr))
254c4762a1bSJed Brown
255c4762a1bSJed Brown!  Assemble matrix
256c4762a1bSJed Brown
257d8606c27SBarry Smith      PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY,ierr))
258d8606c27SBarry Smith      PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY,ierr))
259c4762a1bSJed Brown      if (B .ne. jac) then
260d8606c27SBarry Smith        PetscCall(MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY,ierr))
261d8606c27SBarry Smith        PetscCall(MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY,ierr))
262c4762a1bSJed Brown      endif
263c4762a1bSJed Brown
264c4762a1bSJed Brown      end
265c4762a1bSJed Brown
266c4762a1bSJed Brown      subroutine MyLineSearch(linesearch, lctx, ierr)
267c4762a1bSJed Brown      use petscsnes
268c4762a1bSJed Brown      implicit none
269c4762a1bSJed Brown
270c4762a1bSJed Brown      SNESLineSearch    linesearch
271c4762a1bSJed Brown      SNES              snes
272c4762a1bSJed Brown      integer           lctx
273c4762a1bSJed Brown      Vec               x, f,g, y, w
274c4762a1bSJed Brown      PetscReal         ynorm,gnorm,xnorm
275c4762a1bSJed Brown      PetscErrorCode    ierr
276c4762a1bSJed Brown
277c4762a1bSJed Brown      PetscScalar       mone
278c4762a1bSJed Brown
279c4762a1bSJed Brown      mone = -1.0
280d8606c27SBarry Smith      PetscCall(SNESLineSearchGetSNES(linesearch, snes, ierr))
281d8606c27SBarry Smith      PetscCall(SNESLineSearchGetVecs(linesearch, x, f, y, w, g, ierr))
282d8606c27SBarry Smith      PetscCall(VecNorm(y,NORM_2,ynorm,ierr))
283d8606c27SBarry Smith      PetscCall(VecAXPY(x,mone,y,ierr))
284d8606c27SBarry Smith      PetscCall(SNESComputeFunction(snes,x,f,ierr))
285d8606c27SBarry Smith      PetscCall(VecNorm(f,NORM_2,gnorm,ierr))
286d8606c27SBarry Smith      PetscCall(VecNorm(x,NORM_2,xnorm,ierr))
287d8606c27SBarry Smith      PetscCall(VecNorm(y,NORM_2,ynorm,ierr))
288d8606c27SBarry Smith      PetscCall(SNESLineSearchSetNorms(linesearch, xnorm, gnorm, ynorm,ierr))
289c4762a1bSJed Brown      end
290c4762a1bSJed Brown
291c4762a1bSJed Brown!/*TEST
292c4762a1bSJed Brown!
293c4762a1bSJed Brown!   test:
294c4762a1bSJed Brown!      args: -ksp_gmres_cgs_refinement_type refine_always -snes_monitor_short
295c4762a1bSJed Brown!      requires: !single
296c4762a1bSJed Brown!
297c4762a1bSJed Brown!TEST*/
298