xref: /petsc/src/snes/tutorials/ex1f.F90 (revision e7a95102f46630f317be643b805dc1c3f4655aeb)
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*e7a95102SMartin Diehlmodule ex1f_mod
6*e7a95102SMartin Diehl  use petscvec
7*e7a95102SMartin Diehl  use petscsnesdef
8*e7a95102SMartin Diehl  use petscvec
9*e7a95102SMartin Diehl  use petscmat
10*e7a95102SMartin Diehl  implicit none
11*e7a95102SMartin Diehl
12*e7a95102SMartin Diehlcontains
13*e7a95102SMartin Diehl!
14*e7a95102SMartin Diehl! ------------------------------------------------------------------------
15*e7a95102SMartin Diehl!
16*e7a95102SMartin Diehl!  FormFunction - Evaluates nonlinear function, F(x).
17*e7a95102SMartin Diehl!
18*e7a95102SMartin Diehl!  Input Parameters:
19*e7a95102SMartin Diehl!  snes - the SNES context
20*e7a95102SMartin Diehl!  x - input vector
21*e7a95102SMartin Diehl!  dummy - optional user-defined context (not used here)
22*e7a95102SMartin Diehl!
23*e7a95102SMartin Diehl!  Output Parameter:
24*e7a95102SMartin Diehl!  f - function vector
25*e7a95102SMartin Diehl!
26*e7a95102SMartin Diehl  subroutine FormFunction(snes, x, f, dummy, ierr)
27*e7a95102SMartin Diehl    SNES snes
28*e7a95102SMartin Diehl    Vec x, f
29*e7a95102SMartin Diehl    PetscErrorCode ierr
30*e7a95102SMartin Diehl    integer dummy(*)
31*e7a95102SMartin Diehl
32*e7a95102SMartin Diehl!  Declarations for use with local arrays
33*e7a95102SMartin Diehl    PetscScalar, pointer :: lx_v(:), lf_v(:)
34*e7a95102SMartin Diehl
35*e7a95102SMartin Diehl!  Get pointers to vector data.
36*e7a95102SMartin Diehl!    - VecGetArray() returns a pointer to the data array.
37*e7a95102SMartin Diehl!    - You MUST call VecRestoreArray() when you no longer need access to
38*e7a95102SMartin Diehl!      the array.
39*e7a95102SMartin Diehl
40*e7a95102SMartin Diehl    PetscCall(VecGetArrayRead(x, lx_v, ierr))
41*e7a95102SMartin Diehl    PetscCall(VecGetArray(f, lf_v, ierr))
42*e7a95102SMartin Diehl
43*e7a95102SMartin Diehl!  Compute function
44*e7a95102SMartin Diehl
45*e7a95102SMartin Diehl    lf_v(1) = lx_v(1)*lx_v(1) + lx_v(1)*lx_v(2) - 3.0
46*e7a95102SMartin Diehl    lf_v(2) = lx_v(1)*lx_v(2) + lx_v(2)*lx_v(2) - 6.0
47*e7a95102SMartin Diehl
48*e7a95102SMartin Diehl!  Restore vectors
49*e7a95102SMartin Diehl
50*e7a95102SMartin Diehl    PetscCall(VecRestoreArrayRead(x, lx_v, ierr))
51*e7a95102SMartin Diehl    PetscCall(VecRestoreArray(f, lf_v, ierr))
52*e7a95102SMartin Diehl
53*e7a95102SMartin Diehl  end
54*e7a95102SMartin Diehl
55*e7a95102SMartin Diehl! ---------------------------------------------------------------------
56*e7a95102SMartin Diehl!
57*e7a95102SMartin Diehl!  FormJacobian - Evaluates Jacobian matrix.
58*e7a95102SMartin Diehl!
59*e7a95102SMartin Diehl!  Input Parameters:
60*e7a95102SMartin Diehl!  snes - the SNES context
61*e7a95102SMartin Diehl!  x - input vector
62*e7a95102SMartin Diehl!  dummy - optional user-defined context (not used here)
63*e7a95102SMartin Diehl!
64*e7a95102SMartin Diehl!  Output Parameters:
65*e7a95102SMartin Diehl!  A - Jacobian matrix
66*e7a95102SMartin Diehl!  B - optionally different matrix used to construct the preconditioner
67*e7a95102SMartin Diehl!
68*e7a95102SMartin Diehl  subroutine FormJacobian(snes, X, jac, B, dummy, ierr)
69*e7a95102SMartin Diehl
70*e7a95102SMartin Diehl    SNES snes
71*e7a95102SMartin Diehl    Vec X
72*e7a95102SMartin Diehl    Mat jac, B
73*e7a95102SMartin Diehl    PetscScalar A(4)
74*e7a95102SMartin Diehl    PetscErrorCode ierr
75*e7a95102SMartin Diehl    PetscInt idx(2), i2
76*e7a95102SMartin Diehl    integer dummy(*)
77*e7a95102SMartin Diehl
78*e7a95102SMartin Diehl!  Declarations for use with local arrays
79*e7a95102SMartin Diehl
80*e7a95102SMartin Diehl    PetscScalar, pointer :: lx_v(:)
81*e7a95102SMartin Diehl
82*e7a95102SMartin Diehl!  Get pointer to vector data
83*e7a95102SMartin Diehl
84*e7a95102SMartin Diehl    i2 = 2
85*e7a95102SMartin Diehl    PetscCall(VecGetArrayRead(x, lx_v, ierr))
86*e7a95102SMartin Diehl
87*e7a95102SMartin Diehl!  Compute Jacobian entries and insert into matrix.
88*e7a95102SMartin Diehl!   - Since this is such a small problem, we set all entries for
89*e7a95102SMartin Diehl!     the matrix at once.
90*e7a95102SMartin Diehl!   - Note that MatSetValues() uses 0-based row and column numbers
91*e7a95102SMartin Diehl!     in Fortran as well as in C (as set here in the array idx).
92*e7a95102SMartin Diehl
93*e7a95102SMartin Diehl    idx(1) = 0
94*e7a95102SMartin Diehl    idx(2) = 1
95*e7a95102SMartin Diehl    A(1) = 2.0*lx_v(1) + lx_v(2)
96*e7a95102SMartin Diehl    A(2) = lx_v(1)
97*e7a95102SMartin Diehl    A(3) = lx_v(2)
98*e7a95102SMartin Diehl    A(4) = lx_v(1) + 2.0*lx_v(2)
99*e7a95102SMartin Diehl    PetscCall(MatSetValues(B, i2, idx, i2, idx, A, INSERT_VALUES, ierr))
100*e7a95102SMartin Diehl
101*e7a95102SMartin Diehl!  Restore vector
102*e7a95102SMartin Diehl
103*e7a95102SMartin Diehl    PetscCall(VecRestoreArrayRead(x, lx_v, ierr))
104*e7a95102SMartin Diehl
105*e7a95102SMartin Diehl!  Assemble matrix
106*e7a95102SMartin Diehl
107*e7a95102SMartin Diehl    PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY, ierr))
108*e7a95102SMartin Diehl    PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY, ierr))
109*e7a95102SMartin Diehl    if (B /= jac) then
110*e7a95102SMartin Diehl      PetscCall(MatAssemblyBegin(jac, MAT_FINAL_ASSEMBLY, ierr))
111*e7a95102SMartin Diehl      PetscCall(MatAssemblyEnd(jac, MAT_FINAL_ASSEMBLY, ierr))
112*e7a95102SMartin Diehl    end if
113*e7a95102SMartin Diehl
114*e7a95102SMartin Diehl  end
115*e7a95102SMartin Diehl
116*e7a95102SMartin Diehl  subroutine MyLineSearch(linesearch, lctx, ierr)
117*e7a95102SMartin Diehl
118*e7a95102SMartin Diehl    SNESLineSearch linesearch
119*e7a95102SMartin Diehl    SNES snes
120*e7a95102SMartin Diehl    integer lctx
121*e7a95102SMartin Diehl    Vec x, f, g, y, w
122*e7a95102SMartin Diehl    PetscReal ynorm, gnorm, xnorm
123*e7a95102SMartin Diehl    PetscErrorCode ierr
124*e7a95102SMartin Diehl
125*e7a95102SMartin Diehl    PetscScalar mone
126*e7a95102SMartin Diehl
127*e7a95102SMartin Diehl    mone = -1.0
128*e7a95102SMartin Diehl    PetscCall(SNESLineSearchGetSNES(linesearch, snes, ierr))
129*e7a95102SMartin Diehl    PetscCall(SNESLineSearchGetVecs(linesearch, x, f, y, w, g, ierr))
130*e7a95102SMartin Diehl    PetscCall(VecNorm(y, NORM_2, ynorm, ierr))
131*e7a95102SMartin Diehl    PetscCall(VecAXPY(x, mone, y, ierr))
132*e7a95102SMartin Diehl    PetscCall(SNESComputeFunction(snes, x, f, ierr))
133*e7a95102SMartin Diehl    PetscCall(VecNorm(f, NORM_2, gnorm, ierr))
134*e7a95102SMartin Diehl    PetscCall(VecNorm(x, NORM_2, xnorm, ierr))
135*e7a95102SMartin Diehl    PetscCall(VecNorm(y, NORM_2, ynorm, ierr))
136*e7a95102SMartin Diehl    PetscCall(SNESLineSearchSetNorms(linesearch, xnorm, gnorm, ynorm, ierr))
137*e7a95102SMartin Diehl  end
138*e7a95102SMartin Diehlend module
139*e7a95102SMartin Diehl
140c5e229c2SMartin Diehlprogram main
141c4762a1bSJed Brown  use petsc
142*e7a95102SMartin Diehl  use ex1f_mod
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