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