xref: /petsc/src/snes/tutorials/ex1f.F90 (revision 4820e4ea99a084ae862a8c395f732bc7c0e1a6d0)
1c4762a1bSJed Brown!
2c4762a1bSJed Brown!  Description: Uses the Newton method to solve a two-variable system.
3c4762a1bSJed Brown!
4c4762a1bSJed Brown
5c4762a1bSJed Brownprogram 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
35ce78bad3SBarry Smith  PetscReal, pointer :: rhistory(:)
36ce78bad3SBarry Smith  PetscInt, pointer :: itshistory(:)
37ce78bad3SBarry Smith  PetscInt nhistory
38956f8c0dSBarry Smith#if defined(PETSC_USE_LOG)
39c4762a1bSJed Brown  PetscViewer viewer
40956f8c0dSBarry Smith#endif
41c4762a1bSJed Brown  double precision threshold, oldthreshold
42c4762a1bSJed Brown
43c4762a1bSJed Brown!  Note: Any user-defined Fortran routines (such as FormJacobian)
44c4762a1bSJed Brown!  MUST be declared as external.
45c4762a1bSJed Brown
46c4762a1bSJed Brown  external FormFunction, FormJacobian, MyLineSearch
47c4762a1bSJed Brown
48c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
49c4762a1bSJed Brown!                 Beginning of program
50c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
51c4762a1bSJed Brown
52d8606c27SBarry Smith  PetscCallA(PetscInitialize(ierr))
53d8606c27SBarry Smith  PetscCallA(PetscLogNestedBegin(ierr))
54c4762a1bSJed Brown  threshold = 1.0
55d8606c27SBarry Smith  PetscCallA(PetscLogSetThreshold(threshold, oldthreshold, ierr))
56d8606c27SBarry Smith  PetscCallMPIA(MPI_Comm_size(PETSC_COMM_WORLD, size, ierr))
57d8606c27SBarry Smith  PetscCallMPIA(MPI_Comm_rank(PETSC_COMM_WORLD, rank, ierr))
58*4820e4eaSBarry Smith  PetscCheckA(size == 1, PETSC_COMM_SELF, PETSC_ERR_WRONG_MPI_SIZE, 'Uniprocessor example')
59c4762a1bSJed Brown
60c4762a1bSJed Brown  i2 = 2
61c4762a1bSJed Brown  i20 = 20
62c4762a1bSJed Brown! - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - -
63c4762a1bSJed Brown!  Create nonlinear solver context
64c4762a1bSJed Brown! - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - -
65c4762a1bSJed Brown
66d8606c27SBarry Smith  PetscCallA(SNESCreate(PETSC_COMM_WORLD, snes, ierr))
67c4762a1bSJed Brown
68ce78bad3SBarry Smith  PetscCallA(SNESSetConvergenceHistory(snes, PETSC_NULL_REAL_ARRAY, PETSC_NULL_INTEGER_ARRAY, PETSC_DECIDE, PETSC_FALSE, ierr))
69ce78bad3SBarry Smith
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
106fb842aefSJose E. Roman  PetscCallA(KSPSetTolerances(ksp, tol, PETSC_CURRENT_REAL, PETSC_CURRENT_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))
1219bcc50f1SBarry Smith    PetscCallA(SNESLineSearchShellSetApply(linesearch, MyLineSearch, 0, ierr))
122c4762a1bSJed Brown  end if
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
137ce78bad3SBarry Smith  PetscCallA(SNESGetConvergenceHistory(snes, rhistory, itshistory, nhistory, ierr))
138ce78bad3SBarry Smith  PetscCallA(SNESRestoreConvergenceHistory(snes, rhistory, itshistory, nhistory, ierr))
139ce78bad3SBarry Smith
14091f3e32bSBarry Smith! View solver converged reason; we could instead use the option -snes_converged_reason
141d8606c27SBarry Smith  PetscCallA(SNESConvergedReasonView(snes, PETSC_VIEWER_STDOUT_WORLD, ierr))
14291f3e32bSBarry Smith
143d8606c27SBarry Smith  PetscCallA(SNESGetIterationNumber(snes, its, ierr))
144*4820e4eaSBarry Smith  if (rank == 0) then
145c4762a1bSJed Brown    write (6, 100) its
146c4762a1bSJed Brown  end if
147c4762a1bSJed Brown100 format('Number of SNES iterations = ', i5)
148c4762a1bSJed Brown
149c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
150c4762a1bSJed Brown!  Free work space.  All PETSc objects should be destroyed when they
151c4762a1bSJed Brown!  are no longer needed.
152c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
153c4762a1bSJed Brown
154d8606c27SBarry Smith  PetscCallA(VecDestroy(x, ierr))
155d8606c27SBarry Smith  PetscCallA(VecDestroy(r, ierr))
156d8606c27SBarry Smith  PetscCallA(MatDestroy(J, ierr))
157d8606c27SBarry Smith  PetscCallA(SNESDestroy(snes, ierr))
158956f8c0dSBarry Smith#if defined(PETSC_USE_LOG)
159d8606c27SBarry Smith  PetscCallA(PetscViewerASCIIOpen(PETSC_COMM_WORLD, 'filename.xml', viewer, ierr))
160d8606c27SBarry Smith  PetscCallA(PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_XML, ierr))
161d8606c27SBarry Smith  PetscCallA(PetscLogView(viewer, ierr))
162d8606c27SBarry Smith  PetscCallA(PetscViewerDestroy(viewer, ierr))
163956f8c0dSBarry Smith#endif
164d8606c27SBarry Smith  PetscCallA(PetscFinalize(ierr))
165c4762a1bSJed Brownend
166c4762a1bSJed Brown!
167c4762a1bSJed Brown! ------------------------------------------------------------------------
168c4762a1bSJed Brown!
169c4762a1bSJed Brown!  FormFunction - Evaluates nonlinear function, F(x).
170c4762a1bSJed Brown!
171c4762a1bSJed Brown!  Input Parameters:
172c4762a1bSJed Brown!  snes - the SNES context
173c4762a1bSJed Brown!  x - input vector
174c4762a1bSJed Brown!  dummy - optional user-defined context (not used here)
175c4762a1bSJed Brown!
176c4762a1bSJed Brown!  Output Parameter:
177c4762a1bSJed Brown!  f - function vector
178c4762a1bSJed Brown!
179c4762a1bSJed Brownsubroutine FormFunction(snes, x, f, dummy, ierr)
180ce78bad3SBarry Smith  use petscvec
181ce78bad3SBarry Smith  use petscsnesdef
182c4762a1bSJed Brown  implicit none
183c4762a1bSJed Brown
184c4762a1bSJed Brown  SNES snes
185c4762a1bSJed Brown  Vec x, f
186c4762a1bSJed Brown  PetscErrorCode ierr
187c4762a1bSJed Brown  integer dummy(*)
188c4762a1bSJed Brown
189c4762a1bSJed Brown!  Declarations for use with local arrays
19042ce371bSBarry Smith  PetscScalar, pointer :: lx_v(:), lf_v(:)
191c4762a1bSJed Brown
192c4762a1bSJed Brown!  Get pointers to vector data.
193ce78bad3SBarry Smith!    - VecGetArray() returns a pointer to the data array.
194ce78bad3SBarry Smith!    - You MUST call VecRestoreArray() when you no longer need access to
195c4762a1bSJed Brown!      the array.
196c4762a1bSJed Brown
197ce78bad3SBarry Smith  PetscCall(VecGetArrayRead(x, lx_v, ierr))
198ce78bad3SBarry Smith  PetscCall(VecGetArray(f, lf_v, ierr))
199c4762a1bSJed Brown
200c4762a1bSJed Brown!  Compute function
201c4762a1bSJed Brown
20242ce371bSBarry Smith  lf_v(1) = lx_v(1)*lx_v(1) + lx_v(1)*lx_v(2) - 3.0
20342ce371bSBarry Smith  lf_v(2) = lx_v(1)*lx_v(2) + lx_v(2)*lx_v(2) - 6.0
204c4762a1bSJed Brown
205c4762a1bSJed Brown!  Restore vectors
206c4762a1bSJed Brown
207ce78bad3SBarry Smith  PetscCall(VecRestoreArrayRead(x, lx_v, ierr))
208ce78bad3SBarry Smith  PetscCall(VecRestoreArray(f, lf_v, ierr))
209c4762a1bSJed Brown
210c4762a1bSJed Brownend
211c4762a1bSJed Brown
212c4762a1bSJed Brown! ---------------------------------------------------------------------
213c4762a1bSJed Brown!
214c4762a1bSJed Brown!  FormJacobian - Evaluates Jacobian matrix.
215c4762a1bSJed Brown!
216c4762a1bSJed Brown!  Input Parameters:
217c4762a1bSJed Brown!  snes - the SNES context
218c4762a1bSJed Brown!  x - input vector
219c4762a1bSJed Brown!  dummy - optional user-defined context (not used here)
220c4762a1bSJed Brown!
221c4762a1bSJed Brown!  Output Parameters:
222c4762a1bSJed Brown!  A - Jacobian matrix
2237addb90fSBarry Smith!  B - optionally different matrix used to construct the preconditioner
224c4762a1bSJed Brown!
225c4762a1bSJed Brownsubroutine FormJacobian(snes, X, jac, B, dummy, ierr)
226ce78bad3SBarry Smith  use petscvec
227ce78bad3SBarry Smith  use petscmat
228ce78bad3SBarry Smith  use petscsnesdef
229c4762a1bSJed Brown  implicit none
230c4762a1bSJed Brown
231c4762a1bSJed Brown  SNES snes
232c4762a1bSJed Brown  Vec X
233c4762a1bSJed Brown  Mat jac, B
234c4762a1bSJed Brown  PetscScalar A(4)
235c4762a1bSJed Brown  PetscErrorCode ierr
236c4762a1bSJed Brown  PetscInt idx(2), i2
237c4762a1bSJed Brown  integer dummy(*)
238c4762a1bSJed Brown
239c4762a1bSJed Brown!  Declarations for use with local arrays
240c4762a1bSJed Brown
24142ce371bSBarry Smith  PetscScalar, pointer :: lx_v(:)
242c4762a1bSJed Brown
243c4762a1bSJed Brown!  Get pointer to vector data
244c4762a1bSJed Brown
245c4762a1bSJed Brown  i2 = 2
246ce78bad3SBarry Smith  PetscCall(VecGetArrayRead(x, lx_v, ierr))
247c4762a1bSJed Brown
248c4762a1bSJed Brown!  Compute Jacobian entries and insert into matrix.
249c4762a1bSJed Brown!   - Since this is such a small problem, we set all entries for
250c4762a1bSJed Brown!     the matrix at once.
251c4762a1bSJed Brown!   - Note that MatSetValues() uses 0-based row and column numbers
252c4762a1bSJed Brown!     in Fortran as well as in C (as set here in the array idx).
253c4762a1bSJed Brown
254c4762a1bSJed Brown  idx(1) = 0
255c4762a1bSJed Brown  idx(2) = 1
25642ce371bSBarry Smith  A(1) = 2.0*lx_v(1) + lx_v(2)
25742ce371bSBarry Smith  A(2) = lx_v(1)
25842ce371bSBarry Smith  A(3) = lx_v(2)
25942ce371bSBarry Smith  A(4) = lx_v(1) + 2.0*lx_v(2)
260d8606c27SBarry Smith  PetscCall(MatSetValues(B, i2, idx, i2, idx, A, INSERT_VALUES, ierr))
261c4762a1bSJed Brown
262c4762a1bSJed Brown!  Restore vector
263c4762a1bSJed Brown
264ce78bad3SBarry Smith  PetscCall(VecRestoreArrayRead(x, lx_v, ierr))
265c4762a1bSJed Brown
266c4762a1bSJed Brown!  Assemble matrix
267c4762a1bSJed Brown
268d8606c27SBarry Smith  PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY, ierr))
269d8606c27SBarry Smith  PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY, ierr))
270*4820e4eaSBarry Smith  if (B /= jac) then
271d8606c27SBarry Smith    PetscCall(MatAssemblyBegin(jac, MAT_FINAL_ASSEMBLY, ierr))
272d8606c27SBarry Smith    PetscCall(MatAssemblyEnd(jac, MAT_FINAL_ASSEMBLY, ierr))
273c4762a1bSJed Brown  end if
274c4762a1bSJed Brown
275c4762a1bSJed Brownend
276c4762a1bSJed Brown
277c4762a1bSJed Brownsubroutine MyLineSearch(linesearch, lctx, ierr)
278c4762a1bSJed Brown  use petscsnes
279ce78bad3SBarry Smith  use petscvec
280c4762a1bSJed Brown  implicit none
281c4762a1bSJed Brown
282c4762a1bSJed Brown  SNESLineSearch linesearch
283c4762a1bSJed Brown  SNES snes
284c4762a1bSJed Brown  integer lctx
285c4762a1bSJed Brown  Vec x, f, g, y, w
286c4762a1bSJed Brown  PetscReal ynorm, gnorm, xnorm
287c4762a1bSJed Brown  PetscErrorCode ierr
288c4762a1bSJed Brown
289c4762a1bSJed Brown  PetscScalar mone
290c4762a1bSJed Brown
291c4762a1bSJed Brown  mone = -1.0
292d8606c27SBarry Smith  PetscCall(SNESLineSearchGetSNES(linesearch, snes, ierr))
293d8606c27SBarry Smith  PetscCall(SNESLineSearchGetVecs(linesearch, x, f, y, w, g, ierr))
294d8606c27SBarry Smith  PetscCall(VecNorm(y, NORM_2, ynorm, ierr))
295d8606c27SBarry Smith  PetscCall(VecAXPY(x, mone, y, ierr))
296d8606c27SBarry Smith  PetscCall(SNESComputeFunction(snes, x, f, ierr))
297d8606c27SBarry Smith  PetscCall(VecNorm(f, NORM_2, gnorm, ierr))
298d8606c27SBarry Smith  PetscCall(VecNorm(x, NORM_2, xnorm, ierr))
299d8606c27SBarry Smith  PetscCall(VecNorm(y, NORM_2, ynorm, ierr))
300d8606c27SBarry Smith  PetscCall(SNESLineSearchSetNorms(linesearch, xnorm, gnorm, ynorm, ierr))
301c4762a1bSJed Brownend
302c4762a1bSJed Brown
303c4762a1bSJed Brown!/*TEST
304c4762a1bSJed Brown!
305c4762a1bSJed Brown!   test:
306c4762a1bSJed Brown!      args: -ksp_gmres_cgs_refinement_type refine_always -snes_monitor_short
307c4762a1bSJed Brown!      requires: !single
308c4762a1bSJed Brown!
309c4762a1bSJed Brown!TEST*/
310