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