xref: /petsc/src/snes/tutorials/ex1f.F90 (revision c5e229c2f66f66995aed5443a26600af2aec4a3f)
1c4762a1bSJed Brown!
2c4762a1bSJed Brown!  Description: Uses the Newton method to solve a two-variable system.
3c4762a1bSJed Brown!
4c4762a1bSJed Brown#include <petsc/finclude/petsc.h>
5*c5e229c2SMartin Diehlprogram main
6c4762a1bSJed Brown  use petsc
7c4762a1bSJed Brown  implicit none
8c4762a1bSJed Brown
9c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
10c4762a1bSJed Brown!                   Variable declarations
11c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
12c4762a1bSJed Brown!
13c4762a1bSJed Brown!  Variables:
14c4762a1bSJed Brown!     snes        - nonlinear solver
15c4762a1bSJed Brown!     ksp        - linear solver
16c4762a1bSJed Brown!     pc          - preconditioner context
17c4762a1bSJed Brown!     ksp         - Krylov subspace method context
18c4762a1bSJed Brown!     x, r        - solution, residual vectors
19c4762a1bSJed Brown!     J           - Jacobian matrix
20c4762a1bSJed Brown!     its         - iterations for convergence
21c4762a1bSJed Brown!
22c4762a1bSJed Brown  SNES snes
23c4762a1bSJed Brown  PC pc
24c4762a1bSJed Brown  KSP ksp
25c4762a1bSJed Brown  Vec x, r
26c4762a1bSJed Brown  Mat J
27c4762a1bSJed Brown  SNESLineSearch linesearch
28c4762a1bSJed Brown  PetscErrorCode ierr
29c4762a1bSJed Brown  PetscInt its, i2, i20
30c4762a1bSJed Brown  PetscMPIInt size, rank
31c4762a1bSJed Brown  PetscScalar pfive
32c4762a1bSJed Brown  PetscReal tol
33c4762a1bSJed Brown  PetscBool setls
34ce78bad3SBarry Smith  PetscReal, pointer :: rhistory(:)
35ce78bad3SBarry Smith  PetscInt, pointer :: itshistory(:)
36ce78bad3SBarry Smith  PetscInt nhistory
37956f8c0dSBarry Smith#if defined(PETSC_USE_LOG)
38c4762a1bSJed Brown  PetscViewer viewer
39956f8c0dSBarry Smith#endif
40c4762a1bSJed Brown  double precision threshold, oldthreshold
41c4762a1bSJed Brown
42c4762a1bSJed Brown!  Note: Any user-defined Fortran routines (such as FormJacobian)
43c4762a1bSJed Brown!  MUST be declared as external.
44c4762a1bSJed Brown
45c4762a1bSJed Brown  external FormFunction, FormJacobian, MyLineSearch
46c4762a1bSJed Brown
47c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
48c4762a1bSJed Brown!                 Beginning of program
49c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
50c4762a1bSJed Brown
51d8606c27SBarry Smith  PetscCallA(PetscInitialize(ierr))
52d8606c27SBarry Smith  PetscCallA(PetscLogNestedBegin(ierr))
53c4762a1bSJed Brown  threshold = 1.0
54d8606c27SBarry Smith  PetscCallA(PetscLogSetThreshold(threshold, oldthreshold, ierr))
55d8606c27SBarry Smith  PetscCallMPIA(MPI_Comm_size(PETSC_COMM_WORLD, size, ierr))
56d8606c27SBarry Smith  PetscCallMPIA(MPI_Comm_rank(PETSC_COMM_WORLD, rank, ierr))
574820e4eaSBarry Smith  PetscCheckA(size == 1, PETSC_COMM_SELF, PETSC_ERR_WRONG_MPI_SIZE, 'Uniprocessor example')
58c4762a1bSJed Brown
59c4762a1bSJed Brown  i2 = 2
60c4762a1bSJed Brown  i20 = 20
61c4762a1bSJed Brown! - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - -
62c4762a1bSJed Brown!  Create nonlinear solver context
63c4762a1bSJed Brown! - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - -
64c4762a1bSJed Brown
65d8606c27SBarry Smith  PetscCallA(SNESCreate(PETSC_COMM_WORLD, snes, ierr))
66c4762a1bSJed Brown
67ce78bad3SBarry Smith  PetscCallA(SNESSetConvergenceHistory(snes, PETSC_NULL_REAL_ARRAY, PETSC_NULL_INTEGER_ARRAY, PETSC_DECIDE, PETSC_FALSE, ierr))
68ce78bad3SBarry Smith
69c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
70c4762a1bSJed Brown!  Create matrix and vector data structures; set corresponding routines
71c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
72c4762a1bSJed Brown
73c4762a1bSJed Brown!  Create vectors for solution and nonlinear function
74c4762a1bSJed Brown
75d8606c27SBarry Smith  PetscCallA(VecCreateSeq(PETSC_COMM_SELF, i2, x, ierr))
76d8606c27SBarry Smith  PetscCallA(VecDuplicate(x, r, ierr))
77c4762a1bSJed Brown
78c4762a1bSJed Brown!  Create Jacobian matrix data structure
79c4762a1bSJed Brown
80d8606c27SBarry Smith  PetscCallA(MatCreate(PETSC_COMM_SELF, J, ierr))
81d8606c27SBarry Smith  PetscCallA(MatSetSizes(J, PETSC_DECIDE, PETSC_DECIDE, i2, i2, ierr))
82d8606c27SBarry Smith  PetscCallA(MatSetFromOptions(J, ierr))
83d8606c27SBarry Smith  PetscCallA(MatSetUp(J, ierr))
84c4762a1bSJed Brown
85c4762a1bSJed Brown!  Set function evaluation routine and vector
86c4762a1bSJed Brown
87d8606c27SBarry Smith  PetscCallA(SNESSetFunction(snes, r, FormFunction, 0, ierr))
88c4762a1bSJed Brown
89c4762a1bSJed Brown!  Set Jacobian matrix data structure and Jacobian evaluation routine
90c4762a1bSJed Brown
91d8606c27SBarry Smith  PetscCallA(SNESSetJacobian(snes, J, J, FormJacobian, 0, ierr))
92c4762a1bSJed Brown
93c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
94c4762a1bSJed Brown!  Customize nonlinear solver; set runtime options
95c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
96c4762a1bSJed Brown
97c4762a1bSJed Brown!  Set linear solver defaults for this problem. By extracting the
98c4762a1bSJed Brown!  KSP, KSP, and PC contexts from the SNES context, we can then
99c4762a1bSJed Brown!  directly call any KSP, KSP, and PC routines to set various options.
100c4762a1bSJed Brown
101d8606c27SBarry Smith  PetscCallA(SNESGetKSP(snes, ksp, ierr))
102d8606c27SBarry Smith  PetscCallA(KSPGetPC(ksp, pc, ierr))
103d8606c27SBarry Smith  PetscCallA(PCSetType(pc, PCNONE, ierr))
104c4762a1bSJed Brown  tol = 1.e-4
105fb842aefSJose E. Roman  PetscCallA(KSPSetTolerances(ksp, tol, PETSC_CURRENT_REAL, PETSC_CURRENT_REAL, i20, ierr))
106c4762a1bSJed Brown
107c4762a1bSJed Brown!  Set SNES/KSP/KSP/PC runtime options, e.g.,
108c4762a1bSJed Brown!      -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc>
109c4762a1bSJed Brown!  These options will override those specified above as long as
110c4762a1bSJed Brown!  SNESSetFromOptions() is called _after_ any other customization
111c4762a1bSJed Brown!  routines.
112c4762a1bSJed Brown
113d8606c27SBarry Smith  PetscCallA(SNESSetFromOptions(snes, ierr))
114c4762a1bSJed Brown
115d8606c27SBarry Smith  PetscCallA(PetscOptionsHasName(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-setls', setls, ierr))
116c4762a1bSJed Brown
117c4762a1bSJed Brown  if (setls) then
118d8606c27SBarry Smith    PetscCallA(SNESGetLineSearch(snes, linesearch, ierr))
119d8606c27SBarry Smith    PetscCallA(SNESLineSearchSetType(linesearch, 'shell', ierr))
1209bcc50f1SBarry Smith    PetscCallA(SNESLineSearchShellSetApply(linesearch, MyLineSearch, 0, ierr))
121c4762a1bSJed Brown  end if
122c4762a1bSJed Brown
123c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
124c4762a1bSJed Brown!  Evaluate initial guess; then solve nonlinear system
125c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
126c4762a1bSJed Brown
127c4762a1bSJed Brown!  Note: The user should initialize the vector, x, with the initial guess
128c4762a1bSJed Brown!  for the nonlinear solver prior to calling SNESSolve().  In particular,
129c4762a1bSJed Brown!  to employ an initial guess of zero, the user should explicitly set
130c4762a1bSJed Brown!  this vector to zero by calling VecSet().
131c4762a1bSJed Brown
132c4762a1bSJed Brown  pfive = 0.5
133d8606c27SBarry Smith  PetscCallA(VecSet(x, pfive, ierr))
134d8606c27SBarry Smith  PetscCallA(SNESSolve(snes, PETSC_NULL_VEC, x, ierr))
13591f3e32bSBarry Smith
136ce78bad3SBarry Smith  PetscCallA(SNESGetConvergenceHistory(snes, rhistory, itshistory, nhistory, ierr))
137ce78bad3SBarry Smith  PetscCallA(SNESRestoreConvergenceHistory(snes, rhistory, itshistory, nhistory, ierr))
138ce78bad3SBarry Smith
13991f3e32bSBarry Smith! View solver converged reason; we could instead use the option -snes_converged_reason
140d8606c27SBarry Smith  PetscCallA(SNESConvergedReasonView(snes, PETSC_VIEWER_STDOUT_WORLD, ierr))
14191f3e32bSBarry Smith
142d8606c27SBarry Smith  PetscCallA(SNESGetIterationNumber(snes, its, ierr))
1434820e4eaSBarry Smith  if (rank == 0) then
144c4762a1bSJed Brown    write (6, 100) its
145c4762a1bSJed Brown  end if
146c4762a1bSJed Brown100 format('Number of SNES iterations = ', i5)
147c4762a1bSJed Brown
148c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
149c4762a1bSJed Brown!  Free work space.  All PETSc objects should be destroyed when they
150c4762a1bSJed Brown!  are no longer needed.
151c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
152c4762a1bSJed Brown
153d8606c27SBarry Smith  PetscCallA(VecDestroy(x, ierr))
154d8606c27SBarry Smith  PetscCallA(VecDestroy(r, ierr))
155d8606c27SBarry Smith  PetscCallA(MatDestroy(J, ierr))
156d8606c27SBarry Smith  PetscCallA(SNESDestroy(snes, ierr))
157956f8c0dSBarry Smith#if defined(PETSC_USE_LOG)
158d8606c27SBarry Smith  PetscCallA(PetscViewerASCIIOpen(PETSC_COMM_WORLD, 'filename.xml', viewer, ierr))
159d8606c27SBarry Smith  PetscCallA(PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_XML, ierr))
160d8606c27SBarry Smith  PetscCallA(PetscLogView(viewer, ierr))
161d8606c27SBarry Smith  PetscCallA(PetscViewerDestroy(viewer, ierr))
162956f8c0dSBarry Smith#endif
163d8606c27SBarry Smith  PetscCallA(PetscFinalize(ierr))
164c4762a1bSJed Brownend
165c4762a1bSJed Brown!
166c4762a1bSJed Brown! ------------------------------------------------------------------------
167c4762a1bSJed Brown!
168c4762a1bSJed Brown!  FormFunction - Evaluates nonlinear function, F(x).
169c4762a1bSJed Brown!
170c4762a1bSJed Brown!  Input Parameters:
171c4762a1bSJed Brown!  snes - the SNES context
172c4762a1bSJed Brown!  x - input vector
173c4762a1bSJed Brown!  dummy - optional user-defined context (not used here)
174c4762a1bSJed Brown!
175c4762a1bSJed Brown!  Output Parameter:
176c4762a1bSJed Brown!  f - function vector
177c4762a1bSJed Brown!
178c4762a1bSJed Brownsubroutine FormFunction(snes, x, f, dummy, ierr)
179ce78bad3SBarry Smith  use petscvec
180ce78bad3SBarry Smith  use petscsnesdef
181c4762a1bSJed Brown  implicit none
182c4762a1bSJed Brown
183c4762a1bSJed Brown  SNES snes
184c4762a1bSJed Brown  Vec x, f
185c4762a1bSJed Brown  PetscErrorCode ierr
186c4762a1bSJed Brown  integer dummy(*)
187c4762a1bSJed Brown
188c4762a1bSJed Brown!  Declarations for use with local arrays
18942ce371bSBarry Smith  PetscScalar, pointer :: lx_v(:), lf_v(:)
190c4762a1bSJed Brown
191c4762a1bSJed Brown!  Get pointers to vector data.
192ce78bad3SBarry Smith!    - VecGetArray() returns a pointer to the data array.
193ce78bad3SBarry Smith!    - You MUST call VecRestoreArray() when you no longer need access to
194c4762a1bSJed Brown!      the array.
195c4762a1bSJed Brown
196ce78bad3SBarry Smith  PetscCall(VecGetArrayRead(x, lx_v, ierr))
197ce78bad3SBarry Smith  PetscCall(VecGetArray(f, lf_v, ierr))
198c4762a1bSJed Brown
199c4762a1bSJed Brown!  Compute function
200c4762a1bSJed Brown
20142ce371bSBarry Smith  lf_v(1) = lx_v(1)*lx_v(1) + lx_v(1)*lx_v(2) - 3.0
20242ce371bSBarry Smith  lf_v(2) = lx_v(1)*lx_v(2) + lx_v(2)*lx_v(2) - 6.0
203c4762a1bSJed Brown
204c4762a1bSJed Brown!  Restore vectors
205c4762a1bSJed Brown
206ce78bad3SBarry Smith  PetscCall(VecRestoreArrayRead(x, lx_v, ierr))
207ce78bad3SBarry Smith  PetscCall(VecRestoreArray(f, lf_v, ierr))
208c4762a1bSJed Brown
209c4762a1bSJed Brownend
210c4762a1bSJed Brown
211c4762a1bSJed Brown! ---------------------------------------------------------------------
212c4762a1bSJed Brown!
213c4762a1bSJed Brown!  FormJacobian - Evaluates Jacobian matrix.
214c4762a1bSJed Brown!
215c4762a1bSJed Brown!  Input Parameters:
216c4762a1bSJed Brown!  snes - the SNES context
217c4762a1bSJed Brown!  x - input vector
218c4762a1bSJed Brown!  dummy - optional user-defined context (not used here)
219c4762a1bSJed Brown!
220c4762a1bSJed Brown!  Output Parameters:
221c4762a1bSJed Brown!  A - Jacobian matrix
2227addb90fSBarry Smith!  B - optionally different matrix used to construct the preconditioner
223c4762a1bSJed Brown!
224c4762a1bSJed Brownsubroutine FormJacobian(snes, X, jac, B, dummy, ierr)
225ce78bad3SBarry Smith  use petscvec
226ce78bad3SBarry Smith  use petscmat
227ce78bad3SBarry Smith  use petscsnesdef
228c4762a1bSJed Brown  implicit none
229c4762a1bSJed Brown
230c4762a1bSJed Brown  SNES snes
231c4762a1bSJed Brown  Vec X
232c4762a1bSJed Brown  Mat jac, B
233c4762a1bSJed Brown  PetscScalar A(4)
234c4762a1bSJed Brown  PetscErrorCode ierr
235c4762a1bSJed Brown  PetscInt idx(2), i2
236c4762a1bSJed Brown  integer dummy(*)
237c4762a1bSJed Brown
238c4762a1bSJed Brown!  Declarations for use with local arrays
239c4762a1bSJed Brown
24042ce371bSBarry Smith  PetscScalar, pointer :: lx_v(:)
241c4762a1bSJed Brown
242c4762a1bSJed Brown!  Get pointer to vector data
243c4762a1bSJed Brown
244c4762a1bSJed Brown  i2 = 2
245ce78bad3SBarry Smith  PetscCall(VecGetArrayRead(x, lx_v, ierr))
246c4762a1bSJed Brown
247c4762a1bSJed Brown!  Compute Jacobian entries and insert into matrix.
248c4762a1bSJed Brown!   - Since this is such a small problem, we set all entries for
249c4762a1bSJed Brown!     the matrix at once.
250c4762a1bSJed Brown!   - Note that MatSetValues() uses 0-based row and column numbers
251c4762a1bSJed Brown!     in Fortran as well as in C (as set here in the array idx).
252c4762a1bSJed Brown
253c4762a1bSJed Brown  idx(1) = 0
254c4762a1bSJed Brown  idx(2) = 1
25542ce371bSBarry Smith  A(1) = 2.0*lx_v(1) + lx_v(2)
25642ce371bSBarry Smith  A(2) = lx_v(1)
25742ce371bSBarry Smith  A(3) = lx_v(2)
25842ce371bSBarry Smith  A(4) = lx_v(1) + 2.0*lx_v(2)
259d8606c27SBarry Smith  PetscCall(MatSetValues(B, i2, idx, i2, idx, A, INSERT_VALUES, ierr))
260c4762a1bSJed Brown
261c4762a1bSJed Brown!  Restore vector
262c4762a1bSJed Brown
263ce78bad3SBarry Smith  PetscCall(VecRestoreArrayRead(x, lx_v, ierr))
264c4762a1bSJed Brown
265c4762a1bSJed Brown!  Assemble matrix
266c4762a1bSJed Brown
267d8606c27SBarry Smith  PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY, ierr))
268d8606c27SBarry Smith  PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY, ierr))
2694820e4eaSBarry Smith  if (B /= jac) then
270d8606c27SBarry Smith    PetscCall(MatAssemblyBegin(jac, MAT_FINAL_ASSEMBLY, ierr))
271d8606c27SBarry Smith    PetscCall(MatAssemblyEnd(jac, MAT_FINAL_ASSEMBLY, ierr))
272c4762a1bSJed Brown  end if
273c4762a1bSJed Brown
274c4762a1bSJed Brownend
275c4762a1bSJed Brown
276c4762a1bSJed Brownsubroutine MyLineSearch(linesearch, lctx, ierr)
277c4762a1bSJed Brown  use petscsnes
278ce78bad3SBarry Smith  use petscvec
279c4762a1bSJed Brown  implicit none
280c4762a1bSJed Brown
281c4762a1bSJed Brown  SNESLineSearch linesearch
282c4762a1bSJed Brown  SNES snes
283c4762a1bSJed Brown  integer lctx
284c4762a1bSJed Brown  Vec x, f, g, y, w
285c4762a1bSJed Brown  PetscReal ynorm, gnorm, xnorm
286c4762a1bSJed Brown  PetscErrorCode ierr
287c4762a1bSJed Brown
288c4762a1bSJed Brown  PetscScalar mone
289c4762a1bSJed Brown
290c4762a1bSJed Brown  mone = -1.0
291d8606c27SBarry Smith  PetscCall(SNESLineSearchGetSNES(linesearch, snes, ierr))
292d8606c27SBarry Smith  PetscCall(SNESLineSearchGetVecs(linesearch, x, f, y, w, g, ierr))
293d8606c27SBarry Smith  PetscCall(VecNorm(y, NORM_2, ynorm, ierr))
294d8606c27SBarry Smith  PetscCall(VecAXPY(x, mone, y, ierr))
295d8606c27SBarry Smith  PetscCall(SNESComputeFunction(snes, x, f, ierr))
296d8606c27SBarry Smith  PetscCall(VecNorm(f, NORM_2, gnorm, ierr))
297d8606c27SBarry Smith  PetscCall(VecNorm(x, NORM_2, xnorm, ierr))
298d8606c27SBarry Smith  PetscCall(VecNorm(y, NORM_2, ynorm, ierr))
299d8606c27SBarry Smith  PetscCall(SNESLineSearchSetNorms(linesearch, xnorm, gnorm, ynorm, ierr))
300c4762a1bSJed Brownend
301c4762a1bSJed Brown
302c4762a1bSJed Brown!/*TEST
303c4762a1bSJed Brown!
304c4762a1bSJed Brown!   test:
305c4762a1bSJed Brown!      args: -ksp_gmres_cgs_refinement_type refine_always -snes_monitor_short
306c4762a1bSJed Brown!      requires: !single
307c4762a1bSJed Brown!
308c4762a1bSJed Brown!TEST*/
309