xref: /petsc/src/snes/tests/ex1f.F90 (revision 4e8208cbcbc709572b8abe32f33c78b69c819375)
1c4762a1bSJed Brown!
2c4762a1bSJed Brown!  Description: This example solves a nonlinear system on 1 processor with SNES.
3c4762a1bSJed Brown!  We solve the  Bratu (SFI - solid fuel ignition) problem in a 2D rectangular
4c4762a1bSJed Brown!  domain.  The command line options include:
5c4762a1bSJed Brown!    -par <parameter>, where <parameter> indicates the nonlinearity of the problem
6c4762a1bSJed Brown!       problem SFI:  <parameter> = Bratu parameter (0 <= par <= 6.81)
7c4762a1bSJed Brown!    -mx <xg>, where <xg> = number of grid points in the x-direction
8c4762a1bSJed Brown!    -my <yg>, where <yg> = number of grid points in the y-direction
9c4762a1bSJed Brown!
10c4762a1bSJed Brown
11c4762a1bSJed Brown!
12c4762a1bSJed Brown!  --------------------------------------------------------------------------
13c4762a1bSJed Brown!
14c4762a1bSJed Brown!  Solid Fuel Ignition (SFI) problem.  This problem is modeled by
15c4762a1bSJed Brown!  the partial differential equation
16c4762a1bSJed Brown!
17c4762a1bSJed Brown!          -Laplacian u - lambda*exp(u) = 0,  0 < x,y < 1,
18c4762a1bSJed Brown!
19c4762a1bSJed Brown!  with boundary conditions
20c4762a1bSJed Brown!
21c4762a1bSJed Brown!           u = 0  for  x = 0, x = 1, y = 0, y = 1.
22c4762a1bSJed Brown!
23c4762a1bSJed Brown!  A finite difference approximation with the usual 5-point stencil
24c4762a1bSJed Brown!  is used to discretize the boundary value problem to obtain a nonlinear
25c4762a1bSJed Brown!  system of equations.
26c4762a1bSJed Brown!
27c4762a1bSJed Brown!  The parallel version of this code is snes/tutorials/ex5f.F
28c4762a1bSJed Brown!
29c4762a1bSJed Brown!  --------------------------------------------------------------------------
30c4762a1bSJed Brown#include <petsc/finclude/petscsnes.h>
31c5e229c2SMartin Diehl#include <petsc/finclude/petscdraw.h>
3201fa2b5aSMartin Diehlmodule ex1fmodule
33c4762a1bSJed Brown  use petscsnes
34c4762a1bSJed Brown  implicit none
35e7a95102SMartin Diehlcontains
36e7a95102SMartin Diehl  subroutine postcheck(snes, x, y, w, changed_y, changed_w, ctx, ierr)
37c4762a1bSJed Brown    SNES snes
38c4762a1bSJed Brown    PetscReal norm
39c4762a1bSJed Brown    Vec tmp, x, y, w
40c4762a1bSJed Brown    PetscBool changed_w, changed_y
41c4762a1bSJed Brown    PetscErrorCode ierr
42c4762a1bSJed Brown    PetscInt ctx
43c4762a1bSJed Brown    PetscScalar mone
44*b06eb4cdSBarry Smith    MPIU_Comm comm
45c4762a1bSJed Brown
4624fb275aSStefano Zampini    character(len=PETSC_MAX_PATH_LEN) :: outputString
4724fb275aSStefano Zampini
4824fb275aSStefano Zampini    PetscCallA(PetscObjectGetComm(snes, comm, ierr))
49d8606c27SBarry Smith    PetscCallA(VecDuplicate(x, tmp, ierr))
50c4762a1bSJed Brown    mone = -1.0
51d8606c27SBarry Smith    PetscCallA(VecWAXPY(tmp, mone, x, w, ierr))
52d8606c27SBarry Smith    PetscCallA(VecNorm(tmp, NORM_2, norm, ierr))
53d8606c27SBarry Smith    PetscCallA(VecDestroy(tmp, ierr))
5424fb275aSStefano Zampini    write (outputString, *) norm
5524fb275aSStefano Zampini    PetscCallA(PetscPrintf(comm, 'Norm of search step '//trim(outputString)//'\n', ierr))
56c4762a1bSJed Brown  end
57c4762a1bSJed Brown
58e7a95102SMartin Diehl! ---------------------------------------------------------------------
59e7a95102SMartin Diehl!
60e7a95102SMartin Diehl!  FormInitialGuess - Forms initial approximation.
61e7a95102SMartin Diehl!
62e7a95102SMartin Diehl!  Input Parameter:
63e7a95102SMartin Diehl!  X - vector
64e7a95102SMartin Diehl!
65e7a95102SMartin Diehl!  Output Parameters:
66e7a95102SMartin Diehl!  X - vector
67e7a95102SMartin Diehl!  ierr - error code
68e7a95102SMartin Diehl!
69e7a95102SMartin Diehl!  Notes:
70e7a95102SMartin Diehl!  This routine serves as a wrapper for the lower-level routine
71e7a95102SMartin Diehl!  "ApplicationInitialGuess", where the actual computations are
72e7a95102SMartin Diehl!  done using the standard Fortran style of treating the local
73e7a95102SMartin Diehl!  vector data as a multidimensional array over the local mesh.
74e7a95102SMartin Diehl!  This routine merely accesses the local vector data via
75e7a95102SMartin Diehl!  VecGetArray() and VecRestoreArray().
76e7a95102SMartin Diehl!
77e7a95102SMartin Diehl  subroutine FormInitialGuess(X, ierr)
78e7a95102SMartin Diehl
79e7a95102SMartin Diehl!  Input/output variables:
80e7a95102SMartin Diehl    Vec X
81e7a95102SMartin Diehl    PetscErrorCode ierr
82e7a95102SMartin Diehl
83e7a95102SMartin Diehl!     Declarations for use with local arrays:
84e7a95102SMartin Diehl    PetscScalar, pointer :: lx_v(:)
85e7a95102SMartin Diehl
86e7a95102SMartin Diehl    ierr = 0
87e7a95102SMartin Diehl
88e7a95102SMartin Diehl!  Get a pointer to vector data.
89e7a95102SMartin Diehl!    - VecGetArray() returns a pointer to the data array.
90e7a95102SMartin Diehl!    - You MUST call VecRestoreArray() when you no longer need access to
91e7a95102SMartin Diehl!      the array.
92e7a95102SMartin Diehl
93e7a95102SMartin Diehl    PetscCallA(VecGetArray(X, lx_v, ierr))
94e7a95102SMartin Diehl
95e7a95102SMartin Diehl!  Compute initial guess
96e7a95102SMartin Diehl
97e7a95102SMartin Diehl    PetscCallA(ApplicationInitialGuess(lx_v, ierr))
98e7a95102SMartin Diehl
99e7a95102SMartin Diehl!  Restore vector
100e7a95102SMartin Diehl
101e7a95102SMartin Diehl    PetscCallA(VecRestoreArray(X, lx_v, ierr))
102e7a95102SMartin Diehl
103e7a95102SMartin Diehl  end
104e7a95102SMartin Diehl
105e7a95102SMartin Diehl!  ApplicationInitialGuess - Computes initial approximation, called by
106e7a95102SMartin Diehl!  the higher level routine FormInitialGuess().
107e7a95102SMartin Diehl!
108e7a95102SMartin Diehl!  Input Parameter:
109e7a95102SMartin Diehl!  x - local vector data
110e7a95102SMartin Diehl!
111e7a95102SMartin Diehl!  Output Parameters:
112e7a95102SMartin Diehl!  f - local vector data, f(x)
113e7a95102SMartin Diehl!  ierr - error code
114e7a95102SMartin Diehl!
115e7a95102SMartin Diehl!  Notes:
116e7a95102SMartin Diehl!  This routine uses standard Fortran-style computations over a 2-dim array.
117e7a95102SMartin Diehl!
118e7a95102SMartin Diehl  subroutine ApplicationInitialGuess(x, ierr)
119e7a95102SMartin Diehl
120e7a95102SMartin Diehl!  Common blocks:
121e7a95102SMartin Diehl    PetscReal lambda
122e7a95102SMartin Diehl    PetscInt mx, my
123e7a95102SMartin Diehl    PetscBool fd_coloring
124e7a95102SMartin Diehl    common/params/lambda, mx, my, fd_coloring
125e7a95102SMartin Diehl
126e7a95102SMartin Diehl!  Input/output variables:
127e7a95102SMartin Diehl    PetscScalar x(mx, my)
128e7a95102SMartin Diehl    PetscErrorCode ierr
129e7a95102SMartin Diehl
130e7a95102SMartin Diehl!  Local variables:
131e7a95102SMartin Diehl    PetscInt i, j
132e7a95102SMartin Diehl    PetscReal temp1, temp, hx, hy, one
133e7a95102SMartin Diehl
134e7a95102SMartin Diehl!  Set parameters
135e7a95102SMartin Diehl
136e7a95102SMartin Diehl    ierr = 0
137e7a95102SMartin Diehl    one = 1.0
138e7a95102SMartin Diehl    hx = one/(mx - 1)
139e7a95102SMartin Diehl    hy = one/(my - 1)
140e7a95102SMartin Diehl    temp1 = lambda/(lambda + one)
141e7a95102SMartin Diehl
142e7a95102SMartin Diehl    do j = 1, my
143e7a95102SMartin Diehl      temp = min(j - 1, my - j)*hy
144e7a95102SMartin Diehl      do i = 1, mx
145e7a95102SMartin Diehl        if (i == 1 .or. j == 1 .or. i == mx .or. j == my) then
146e7a95102SMartin Diehl          x(i, j) = 0.0
147e7a95102SMartin Diehl        else
148e7a95102SMartin Diehl          x(i, j) = temp1*sqrt(min(min(i - 1, mx - i)*hx, temp))
149e7a95102SMartin Diehl        end if
150e7a95102SMartin Diehl      end do
151e7a95102SMartin Diehl    end do
152e7a95102SMartin Diehl
153e7a95102SMartin Diehl  end
154e7a95102SMartin Diehl
155e7a95102SMartin Diehl! ---------------------------------------------------------------------
156e7a95102SMartin Diehl!
157e7a95102SMartin Diehl!  FormFunction - Evaluates nonlinear function, F(x).
158e7a95102SMartin Diehl!
159e7a95102SMartin Diehl!  Input Parameters:
160e7a95102SMartin Diehl!  snes  - the SNES context
161e7a95102SMartin Diehl!  X     - input vector
162e7a95102SMartin Diehl!  dummy - optional user-defined context, as set by SNESSetFunction()
163e7a95102SMartin Diehl!          (not used here)
164e7a95102SMartin Diehl!
165e7a95102SMartin Diehl!  Output Parameter:
166e7a95102SMartin Diehl!  F     - vector with newly computed function
167e7a95102SMartin Diehl!
168e7a95102SMartin Diehl!  Notes:
169e7a95102SMartin Diehl!  This routine serves as a wrapper for the lower-level routine
170e7a95102SMartin Diehl!  "ApplicationFunction", where the actual computations are
171e7a95102SMartin Diehl!  done using the standard Fortran style of treating the local
172e7a95102SMartin Diehl!  vector data as a multidimensional array over the local mesh.
173e7a95102SMartin Diehl!  This routine merely accesses the local vector data via
174e7a95102SMartin Diehl!  VecGetArray() and VecRestoreArray().
175e7a95102SMartin Diehl!
176e7a95102SMartin Diehl  subroutine FormFunction(snes, X, F, fdcoloring, ierr)
177e7a95102SMartin Diehl
178e7a95102SMartin Diehl!  Input/output variables:
179e7a95102SMartin Diehl    SNES snes
180e7a95102SMartin Diehl    Vec X, F
181e7a95102SMartin Diehl    PetscErrorCode ierr
182e7a95102SMartin Diehl    MatFDColoring fdcoloring
183e7a95102SMartin Diehl
184e7a95102SMartin Diehl!  Common blocks:
185e7a95102SMartin Diehl    PetscReal lambda
186e7a95102SMartin Diehl    PetscInt mx, my
187e7a95102SMartin Diehl    PetscBool fd_coloring
188e7a95102SMartin Diehl    common/params/lambda, mx, my, fd_coloring
189e7a95102SMartin Diehl
190e7a95102SMartin Diehl!  Declarations for use with local arrays:
191e7a95102SMartin Diehl    PetscScalar, pointer :: lx_v(:), lf_v(:)
192e7a95102SMartin Diehl    PetscInt, pointer :: indices(:)
193e7a95102SMartin Diehl
194e7a95102SMartin Diehl!  Get pointers to vector data.
195e7a95102SMartin Diehl!    - VecGetArray() returns a pointer to the data array.
196e7a95102SMartin Diehl!    - You MUST call VecRestoreArray() when you no longer need access to
197e7a95102SMartin Diehl!      the array.
198e7a95102SMartin Diehl
199e7a95102SMartin Diehl    PetscCallA(VecGetArrayRead(X, lx_v, ierr))
200e7a95102SMartin Diehl    PetscCallA(VecGetArray(F, lf_v, ierr))
201e7a95102SMartin Diehl
202e7a95102SMartin Diehl!  Compute function
203e7a95102SMartin Diehl
204e7a95102SMartin Diehl    PetscCallA(ApplicationFunction(lx_v, lf_v, ierr))
205e7a95102SMartin Diehl
206e7a95102SMartin Diehl!  Restore vectors
207e7a95102SMartin Diehl
208e7a95102SMartin Diehl    PetscCallA(VecRestoreArrayRead(X, lx_v, ierr))
209e7a95102SMartin Diehl    PetscCallA(VecRestoreArray(F, lf_v, ierr))
210e7a95102SMartin Diehl
211e7a95102SMartin Diehl    PetscCallA(PetscLogFlops(11.0d0*mx*my, ierr))
212e7a95102SMartin Diehl!
213e7a95102SMartin Diehl!     fdcoloring is in the common block and used here ONLY to test the
214e7a95102SMartin Diehl!     calls to MatFDColoringGetPerturbedColumns() and  MatFDColoringRestorePerturbedColumns()
215e7a95102SMartin Diehl!
216e7a95102SMartin Diehl    if (fd_coloring) then
217e7a95102SMartin Diehl      PetscCallA(MatFDColoringGetPerturbedColumns(fdcoloring, PETSC_NULL_INTEGER, indices, ierr))
218e7a95102SMartin Diehl      print *, 'Indices from GetPerturbedColumns'
219e7a95102SMartin Diehl      write (*, 1000) indices
220e7a95102SMartin Diehl1000  format(50i4)
221e7a95102SMartin Diehl      PetscCallA(MatFDColoringRestorePerturbedColumns(fdcoloring, PETSC_NULL_INTEGER, indices, ierr))
222e7a95102SMartin Diehl    end if
223e7a95102SMartin Diehl  end
224e7a95102SMartin Diehl
225e7a95102SMartin Diehl! ---------------------------------------------------------------------
226e7a95102SMartin Diehl!
227e7a95102SMartin Diehl!  ApplicationFunction - Computes nonlinear function, called by
228e7a95102SMartin Diehl!  the higher level routine FormFunction().
229e7a95102SMartin Diehl!
230e7a95102SMartin Diehl!  Input Parameter:
231e7a95102SMartin Diehl!  x    - local vector data
232e7a95102SMartin Diehl!
233e7a95102SMartin Diehl!  Output Parameters:
234e7a95102SMartin Diehl!  f    - local vector data, f(x)
235e7a95102SMartin Diehl!  ierr - error code
236e7a95102SMartin Diehl!
237e7a95102SMartin Diehl!  Notes:
238e7a95102SMartin Diehl!  This routine uses standard Fortran-style computations over a 2-dim array.
239e7a95102SMartin Diehl!
240e7a95102SMartin Diehl  subroutine ApplicationFunction(x, f, ierr)
241e7a95102SMartin Diehl
242e7a95102SMartin Diehl!  Common blocks:
243e7a95102SMartin Diehl    PetscReal lambda
244e7a95102SMartin Diehl    PetscInt mx, my
245e7a95102SMartin Diehl    PetscBool fd_coloring
246e7a95102SMartin Diehl    common/params/lambda, mx, my, fd_coloring
247e7a95102SMartin Diehl
248e7a95102SMartin Diehl!  Input/output variables:
249e7a95102SMartin Diehl    PetscScalar x(mx, my), f(mx, my)
250e7a95102SMartin Diehl    PetscErrorCode ierr
251e7a95102SMartin Diehl
252e7a95102SMartin Diehl!  Local variables:
253e7a95102SMartin Diehl    PetscScalar two, one, hx, hy
254e7a95102SMartin Diehl    PetscScalar hxdhy, hydhx, sc
255e7a95102SMartin Diehl    PetscScalar u, uxx, uyy
256e7a95102SMartin Diehl    PetscInt i, j
257e7a95102SMartin Diehl
258e7a95102SMartin Diehl    ierr = 0
259e7a95102SMartin Diehl    one = 1.0
260e7a95102SMartin Diehl    two = 2.0
261e7a95102SMartin Diehl    hx = one/(mx - 1)
262e7a95102SMartin Diehl    hy = one/(my - 1)
263e7a95102SMartin Diehl    sc = hx*hy*lambda
264e7a95102SMartin Diehl    hxdhy = hx/hy
265e7a95102SMartin Diehl    hydhx = hy/hx
266e7a95102SMartin Diehl
267e7a95102SMartin Diehl!  Compute function
268e7a95102SMartin Diehl
269e7a95102SMartin Diehl    do j = 1, my
270e7a95102SMartin Diehl      do i = 1, mx
271e7a95102SMartin Diehl        if (i == 1 .or. j == 1 .or. i == mx .or. j == my) then
272e7a95102SMartin Diehl          f(i, j) = x(i, j)
273e7a95102SMartin Diehl        else
274e7a95102SMartin Diehl          u = x(i, j)
275e7a95102SMartin Diehl          uxx = hydhx*(two*u - x(i - 1, j) - x(i + 1, j))
276e7a95102SMartin Diehl          uyy = hxdhy*(two*u - x(i, j - 1) - x(i, j + 1))
277e7a95102SMartin Diehl          f(i, j) = uxx + uyy - sc*exp(u)
278e7a95102SMartin Diehl        end if
279e7a95102SMartin Diehl      end do
280e7a95102SMartin Diehl    end do
281e7a95102SMartin Diehl
282e7a95102SMartin Diehl  end
283e7a95102SMartin Diehl
284e7a95102SMartin Diehl! ---------------------------------------------------------------------
285e7a95102SMartin Diehl!
286e7a95102SMartin Diehl!  FormJacobian - Evaluates Jacobian matrix.
287e7a95102SMartin Diehl!
288e7a95102SMartin Diehl!  Input Parameters:
289e7a95102SMartin Diehl!  snes    - the SNES context
290e7a95102SMartin Diehl!  x       - input vector
291e7a95102SMartin Diehl!  dummy   - optional user-defined context, as set by SNESSetJacobian()
292e7a95102SMartin Diehl!            (not used here)
293e7a95102SMartin Diehl!
294e7a95102SMartin Diehl!  Output Parameters:
295e7a95102SMartin Diehl!  jac      - Jacobian matrix
296e7a95102SMartin Diehl!  jac_prec - optionally different matrix used to construct the preconditioner (not used here)
297e7a95102SMartin Diehl!
298e7a95102SMartin Diehl!  Notes:
299e7a95102SMartin Diehl!  This routine serves as a wrapper for the lower-level routine
300e7a95102SMartin Diehl!  "ApplicationJacobian", where the actual computations are
301e7a95102SMartin Diehl!  done using the standard Fortran style of treating the local
302e7a95102SMartin Diehl!  vector data as a multidimensional array over the local mesh.
303e7a95102SMartin Diehl!  This routine merely accesses the local vector data via
304e7a95102SMartin Diehl!  VecGetArray() and VecRestoreArray().
305e7a95102SMartin Diehl!
306e7a95102SMartin Diehl  subroutine FormJacobian(snes, X, jac, jac_prec, dummy, ierr)
307e7a95102SMartin Diehl
308e7a95102SMartin Diehl!  Input/output variables:
309e7a95102SMartin Diehl    SNES snes
310e7a95102SMartin Diehl    Vec X
311e7a95102SMartin Diehl    Mat jac, jac_prec
312e7a95102SMartin Diehl    PetscErrorCode ierr
313e7a95102SMartin Diehl    integer dummy
314e7a95102SMartin Diehl
315e7a95102SMartin Diehl!  Common blocks:
316e7a95102SMartin Diehl    PetscReal lambda
317e7a95102SMartin Diehl    PetscInt mx, my
318e7a95102SMartin Diehl    PetscBool fd_coloring
319e7a95102SMartin Diehl    common/params/lambda, mx, my, fd_coloring
320e7a95102SMartin Diehl
321e7a95102SMartin Diehl!  Declarations for use with local array:
322e7a95102SMartin Diehl    PetscScalar, pointer :: lx_v(:)
323e7a95102SMartin Diehl
324e7a95102SMartin Diehl!  Get a pointer to vector data
325e7a95102SMartin Diehl
326e7a95102SMartin Diehl    PetscCallA(VecGetArrayRead(X, lx_v, ierr))
327e7a95102SMartin Diehl
328e7a95102SMartin Diehl!  Compute Jacobian entries
329e7a95102SMartin Diehl
330e7a95102SMartin Diehl    PetscCallA(ApplicationJacobian(lx_v, jac, jac_prec, ierr))
331e7a95102SMartin Diehl
332e7a95102SMartin Diehl!  Restore vector
333e7a95102SMartin Diehl
334e7a95102SMartin Diehl    PetscCallA(VecRestoreArrayRead(X, lx_v, ierr))
335e7a95102SMartin Diehl
336e7a95102SMartin Diehl!  Assemble matrix
337e7a95102SMartin Diehl
338e7a95102SMartin Diehl    PetscCallA(MatAssemblyBegin(jac_prec, MAT_FINAL_ASSEMBLY, ierr))
339e7a95102SMartin Diehl    PetscCallA(MatAssemblyEnd(jac_prec, MAT_FINAL_ASSEMBLY, ierr))
340e7a95102SMartin Diehl
341e7a95102SMartin Diehl  end
342e7a95102SMartin Diehl
343e7a95102SMartin Diehl! ---------------------------------------------------------------------
344e7a95102SMartin Diehl!
345e7a95102SMartin Diehl!  ApplicationJacobian - Computes Jacobian matrix, called by
346e7a95102SMartin Diehl!  the higher level routine FormJacobian().
347e7a95102SMartin Diehl!
348e7a95102SMartin Diehl!  Input Parameters:
349e7a95102SMartin Diehl!  x        - local vector data
350e7a95102SMartin Diehl!
351e7a95102SMartin Diehl!  Output Parameters:
352e7a95102SMartin Diehl!  jac      - Jacobian matrix
353e7a95102SMartin Diehl!  jac_prec - optionally different matrix used to construct the preconditioner (not used here)
354e7a95102SMartin Diehl!  ierr     - error code
355e7a95102SMartin Diehl!
356e7a95102SMartin Diehl!  Notes:
357e7a95102SMartin Diehl!  This routine uses standard Fortran-style computations over a 2-dim array.
358e7a95102SMartin Diehl!
359e7a95102SMartin Diehl  subroutine ApplicationJacobian(x, jac, jac_prec, ierr)
360e7a95102SMartin Diehl!  Common blocks:
361e7a95102SMartin Diehl    PetscReal lambda
362e7a95102SMartin Diehl    PetscInt mx, my
363e7a95102SMartin Diehl    PetscBool fd_coloring
364e7a95102SMartin Diehl    common/params/lambda, mx, my, fd_coloring
365e7a95102SMartin Diehl
366e7a95102SMartin Diehl!  Input/output variables:
367e7a95102SMartin Diehl    PetscScalar x(mx, my)
368e7a95102SMartin Diehl    Mat jac, jac_prec
369e7a95102SMartin Diehl    PetscErrorCode ierr
370e7a95102SMartin Diehl
371e7a95102SMartin Diehl!  Local variables:
372e7a95102SMartin Diehl    PetscInt i, j, row(1), col(5), i1, i5
373e7a95102SMartin Diehl    PetscScalar two, one, hx, hy
374e7a95102SMartin Diehl    PetscScalar hxdhy, hydhx, sc, v(5)
375e7a95102SMartin Diehl
376e7a95102SMartin Diehl!  Set parameters
377e7a95102SMartin Diehl
378e7a95102SMartin Diehl    i1 = 1
379e7a95102SMartin Diehl    i5 = 5
380e7a95102SMartin Diehl    one = 1.0
381e7a95102SMartin Diehl    two = 2.0
382e7a95102SMartin Diehl    hx = one/(mx - 1)
383e7a95102SMartin Diehl    hy = one/(my - 1)
384e7a95102SMartin Diehl    sc = hx*hy
385e7a95102SMartin Diehl    hxdhy = hx/hy
386e7a95102SMartin Diehl    hydhx = hy/hx
387e7a95102SMartin Diehl
388e7a95102SMartin Diehl!  Compute entries of the Jacobian matrix
389e7a95102SMartin Diehl!   - Here, we set all entries for a particular row at once.
390e7a95102SMartin Diehl!   - Note that MatSetValues() uses 0-based row and column numbers
391e7a95102SMartin Diehl!     in Fortran as well as in C.
392e7a95102SMartin Diehl
393e7a95102SMartin Diehl    do j = 1, my
394e7a95102SMartin Diehl      row(1) = (j - 1)*mx - 1
395e7a95102SMartin Diehl      do i = 1, mx
396e7a95102SMartin Diehl        row(1) = row(1) + 1
397e7a95102SMartin Diehl!           boundary points
398e7a95102SMartin Diehl        if (i == 1 .or. j == 1 .or. i == mx .or. j == my) then
399e7a95102SMartin Diehl          PetscCallA(MatSetValues(jac_prec, i1, row, i1, row, [one], INSERT_VALUES, ierr))
400e7a95102SMartin Diehl!           interior grid points
401e7a95102SMartin Diehl        else
402e7a95102SMartin Diehl          v(1) = -hxdhy
403e7a95102SMartin Diehl          v(2) = -hydhx
404e7a95102SMartin Diehl          v(3) = two*(hydhx + hxdhy) - sc*lambda*exp(x(i, j))
405e7a95102SMartin Diehl          v(4) = -hydhx
406e7a95102SMartin Diehl          v(5) = -hxdhy
407e7a95102SMartin Diehl          col(1) = row(1) - mx
408e7a95102SMartin Diehl          col(2) = row(1) - 1
409e7a95102SMartin Diehl          col(3) = row(1)
410e7a95102SMartin Diehl          col(4) = row(1) + 1
411e7a95102SMartin Diehl          col(5) = row(1) + mx
412e7a95102SMartin Diehl          PetscCallA(MatSetValues(jac_prec, i1, row, i5, col, v, INSERT_VALUES, ierr))
413e7a95102SMartin Diehl        end if
414e7a95102SMartin Diehl      end do
415e7a95102SMartin Diehl    end do
416e7a95102SMartin Diehl
417e7a95102SMartin Diehl  end
418e7a95102SMartin Diehl
41901fa2b5aSMartin Diehlend module ex1fmodule
420c4762a1bSJed Brownprogram main
421ce78bad3SBarry Smith  use petscdraw
422c4762a1bSJed Brown  use petscsnes
42301fa2b5aSMartin Diehl  use ex1fmodule
424c4762a1bSJed Brown  implicit none
425c4762a1bSJed Brown!
426c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
427c4762a1bSJed Brown!                   Variable declarations
428c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
429c4762a1bSJed Brown!
430c4762a1bSJed Brown!  Variables:
431c4762a1bSJed Brown!     snes        - nonlinear solver
432c4762a1bSJed Brown!     x, r        - solution, residual vectors
433c4762a1bSJed Brown!     J           - Jacobian matrix
434c4762a1bSJed Brown!     its         - iterations for convergence
435c4762a1bSJed Brown!     matrix_free - flag - 1 indicates matrix-free version
436c4762a1bSJed Brown!     lambda      - nonlinearity parameter
437c4762a1bSJed Brown!     draw        - drawing context
438c4762a1bSJed Brown!
439c4762a1bSJed Brown  SNES snes
440c4762a1bSJed Brown  MatColoring mc
441c4762a1bSJed Brown  Vec x, r
442c4762a1bSJed Brown  PetscDraw draw
443c4762a1bSJed Brown  Mat J
444c4762a1bSJed Brown  PetscBool matrix_free, flg, fd_coloring
445c4762a1bSJed Brown  PetscErrorCode ierr
446c4762a1bSJed Brown  PetscInt its, N, mx, my, i5
447c4762a1bSJed Brown  PetscMPIInt size, rank
448c4762a1bSJed Brown  PetscReal lambda_max, lambda_min, lambda
449c4762a1bSJed Brown  MatFDColoring fdcoloring
450c4762a1bSJed Brown  ISColoring iscoloring
451c4762a1bSJed Brown  PetscBool pc
452ce78bad3SBarry Smith  integer4 imx, imy
45324fb275aSStefano Zampini  character(len=PETSC_MAX_PATH_LEN) :: outputString
45442ce371bSBarry Smith  PetscScalar, pointer :: lx_v(:)
455ce78bad3SBarry Smith  integer4 xl, yl, width, height
456c4762a1bSJed Brown
457c4762a1bSJed Brown!  Store parameters in common block
458c4762a1bSJed Brown
459c4762a1bSJed Brown  common/params/lambda, mx, my, fd_coloring
460c4762a1bSJed Brown
461c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
462c4762a1bSJed Brown!  Initialize program
463c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
464c4762a1bSJed Brown
465d8606c27SBarry Smith  PetscCallA(PetscInitialize(ierr))
466d8606c27SBarry Smith  PetscCallMPIA(MPI_Comm_size(PETSC_COMM_WORLD, size, ierr))
467d8606c27SBarry Smith  PetscCallMPIA(MPI_Comm_rank(PETSC_COMM_WORLD, rank, ierr))
468c4762a1bSJed Brown
4694820e4eaSBarry Smith  PetscCheckA(size == 1, PETSC_COMM_SELF, PETSC_ERR_WRONG_MPI_SIZE, 'This is a uniprocessor example only')
470c4762a1bSJed Brown
471c4762a1bSJed Brown!  Initialize problem parameters
472c4762a1bSJed Brown  i5 = 5
473c4762a1bSJed Brown  lambda_max = 6.81
474c4762a1bSJed Brown  lambda_min = 0.0
475c4762a1bSJed Brown  lambda = 6.0
476c4762a1bSJed Brown  mx = 4
477c4762a1bSJed Brown  my = 4
478d8606c27SBarry Smith  PetscCallA(PetscOptionsGetInt(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-mx', mx, flg, ierr))
479d8606c27SBarry Smith  PetscCallA(PetscOptionsGetInt(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-my', my, flg, ierr))
480d8606c27SBarry Smith  PetscCallA(PetscOptionsGetReal(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-par', lambda, flg, ierr))
4814820e4eaSBarry Smith  PetscCheckA(lambda < lambda_max .and. lambda > lambda_min, PETSC_COMM_SELF, PETSC_ERR_USER, 'Lambda out of range ')
482c4762a1bSJed Brown  N = mx*my
483c4762a1bSJed Brown  pc = PETSC_FALSE
484d8606c27SBarry Smith  PetscCallA(PetscOptionsGetBool(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-pc', pc, PETSC_NULL_BOOL, ierr))
485c4762a1bSJed Brown
486c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
487c4762a1bSJed Brown!  Create nonlinear solver context
488c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
489c4762a1bSJed Brown
490d8606c27SBarry Smith  PetscCallA(SNESCreate(PETSC_COMM_WORLD, snes, ierr))
491c4762a1bSJed Brown
492c4762a1bSJed Brown  if (pc .eqv. PETSC_TRUE) then
493d8606c27SBarry Smith    PetscCallA(SNESSetType(snes, SNESNEWTONTR, ierr))
494d8606c27SBarry Smith    PetscCallA(SNESNewtonTRSetPostCheck(snes, postcheck, snes, ierr))
495c4762a1bSJed Brown  end if
496c4762a1bSJed Brown
497c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
498c4762a1bSJed Brown!  Create vector data structures; set function evaluation routine
499c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
500c4762a1bSJed Brown
501d8606c27SBarry Smith  PetscCallA(VecCreate(PETSC_COMM_WORLD, x, ierr))
502d8606c27SBarry Smith  PetscCallA(VecSetSizes(x, PETSC_DECIDE, N, ierr))
503d8606c27SBarry Smith  PetscCallA(VecSetFromOptions(x, ierr))
504d8606c27SBarry Smith  PetscCallA(VecDuplicate(x, r, ierr))
505c4762a1bSJed Brown
506c4762a1bSJed Brown!  Set function evaluation routine and vector.  Whenever the nonlinear
507c4762a1bSJed Brown!  solver needs to evaluate the nonlinear function, it will call this
508c4762a1bSJed Brown!  routine.
509c4762a1bSJed Brown!   - Note that the final routine argument is the user-defined
510c4762a1bSJed Brown!     context that provides application-specific data for the
511c4762a1bSJed Brown!     function evaluation routine.
512c4762a1bSJed Brown
513d8606c27SBarry Smith  PetscCallA(SNESSetFunction(snes, r, FormFunction, fdcoloring, ierr))
514c4762a1bSJed Brown
515c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
516c4762a1bSJed Brown!  Create matrix data structure; set Jacobian evaluation routine
517c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
518c4762a1bSJed Brown
519c4762a1bSJed Brown!  Create matrix. Here we only approximately preallocate storage space
520c4762a1bSJed Brown!  for the Jacobian.  See the users manual for a discussion of better
521c4762a1bSJed Brown!  techniques for preallocating matrix memory.
522c4762a1bSJed Brown
523d8606c27SBarry Smith  PetscCallA(PetscOptionsHasName(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-snes_mf', matrix_free, ierr))
524c4762a1bSJed Brown  if (.not. matrix_free) then
5255d83a8b1SBarry Smith    PetscCallA(MatCreateSeqAIJ(PETSC_COMM_WORLD, N, N, i5, PETSC_NULL_INTEGER_ARRAY, J, ierr))
526c4762a1bSJed Brown  end if
527c4762a1bSJed Brown
528c4762a1bSJed Brown!
529c4762a1bSJed Brown!     This option will cause the Jacobian to be computed via finite differences
530c4762a1bSJed Brown!    efficiently using a coloring of the columns of the matrix.
531c4762a1bSJed Brown!
532c4762a1bSJed Brown  fd_coloring = .false.
533d8606c27SBarry Smith  PetscCallA(PetscOptionsHasName(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-snes_fd_coloring', fd_coloring, ierr))
534c4762a1bSJed Brown  if (fd_coloring) then
535c4762a1bSJed Brown
536c4762a1bSJed Brown!
537c4762a1bSJed Brown!      This initializes the nonzero structure of the Jacobian. This is artificial
538c4762a1bSJed Brown!      because clearly if we had a routine to compute the Jacobian we won't need
539c4762a1bSJed Brown!      to use finite differences.
540c4762a1bSJed Brown!
541d8606c27SBarry Smith    PetscCallA(FormJacobian(snes, x, J, J, 0, ierr))
542c4762a1bSJed Brown!
543c4762a1bSJed Brown!       Color the matrix, i.e. determine groups of columns that share no common
544a5b23f4aSJose E. Roman!      rows. These columns in the Jacobian can all be computed simultaneously.
545c4762a1bSJed Brown!
546d8606c27SBarry Smith    PetscCallA(MatColoringCreate(J, mc, ierr))
547d8606c27SBarry Smith    PetscCallA(MatColoringSetType(mc, MATCOLORINGNATURAL, ierr))
548d8606c27SBarry Smith    PetscCallA(MatColoringSetFromOptions(mc, ierr))
549d8606c27SBarry Smith    PetscCallA(MatColoringApply(mc, iscoloring, ierr))
550d8606c27SBarry Smith    PetscCallA(MatColoringDestroy(mc, ierr))
551c4762a1bSJed Brown!
552c4762a1bSJed Brown!       Create the data structure that SNESComputeJacobianDefaultColor() uses
553c4762a1bSJed Brown!       to compute the actual Jacobians via finite differences.
554c4762a1bSJed Brown!
555d8606c27SBarry Smith    PetscCallA(MatFDColoringCreate(J, iscoloring, fdcoloring, ierr))
556d8606c27SBarry Smith    PetscCallA(MatFDColoringSetFunction(fdcoloring, FormFunction, fdcoloring, ierr))
557d8606c27SBarry Smith    PetscCallA(MatFDColoringSetFromOptions(fdcoloring, ierr))
558d8606c27SBarry Smith    PetscCallA(MatFDColoringSetUp(J, iscoloring, fdcoloring, ierr))
559c4762a1bSJed Brown!
560c4762a1bSJed Brown!        Tell SNES to use the routine SNESComputeJacobianDefaultColor()
561c4762a1bSJed Brown!      to compute Jacobians.
562c4762a1bSJed Brown!
563d8606c27SBarry Smith    PetscCallA(SNESSetJacobian(snes, J, J, SNESComputeJacobianDefaultColor, fdcoloring, ierr))
564d8606c27SBarry Smith    PetscCallA(ISColoringDestroy(iscoloring, ierr))
565c4762a1bSJed Brown
566c4762a1bSJed Brown  else if (.not. matrix_free) then
567c4762a1bSJed Brown
568c4762a1bSJed Brown!  Set Jacobian matrix data structure and default Jacobian evaluation
569c4762a1bSJed Brown!  routine.  Whenever the nonlinear solver needs to compute the
570c4762a1bSJed Brown!  Jacobian matrix, it will call this routine.
571c4762a1bSJed Brown!   - Note that the final routine argument is the user-defined
572c4762a1bSJed Brown!     context that provides application-specific data for the
573c4762a1bSJed Brown!     Jacobian evaluation routine.
574c4762a1bSJed Brown!   - The user can override with:
575c4762a1bSJed Brown!      -snes_fd : default finite differencing approximation of Jacobian
576c4762a1bSJed Brown!      -snes_mf : matrix-free Newton-Krylov method with no preconditioning
577c4762a1bSJed Brown!                 (unless user explicitly sets preconditioner)
5787addb90fSBarry Smith!      -snes_mf_operator : form matrix from which to construct the preconditioner as set by the user,
579c4762a1bSJed Brown!                          but use matrix-free approx for Jacobian-vector
580c4762a1bSJed Brown!                          products within Newton-Krylov method
581c4762a1bSJed Brown!
582d8606c27SBarry Smith    PetscCallA(SNESSetJacobian(snes, J, J, FormJacobian, 0, ierr))
583c4762a1bSJed Brown  end if
584c4762a1bSJed Brown
585c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
586c4762a1bSJed Brown!  Customize nonlinear solver; set runtime options
587c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
588c4762a1bSJed Brown
589c4762a1bSJed Brown!  Set runtime options (e.g., -snes_monitor -snes_rtol <rtol> -ksp_type <type>)
590c4762a1bSJed Brown
591d8606c27SBarry Smith  PetscCallA(SNESSetFromOptions(snes, ierr))
592c4762a1bSJed Brown
593c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
594c4762a1bSJed Brown!  Evaluate initial guess; then solve nonlinear system.
595c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
596c4762a1bSJed Brown
597c4762a1bSJed Brown!  Note: The user should initialize the vector, x, with the initial guess
598c4762a1bSJed Brown!  for the nonlinear solver prior to calling SNESSolve().  In particular,
599c4762a1bSJed Brown!  to employ an initial guess of zero, the user should explicitly set
600c4762a1bSJed Brown!  this vector to zero by calling VecSet().
601c4762a1bSJed Brown
602d8606c27SBarry Smith  PetscCallA(FormInitialGuess(x, ierr))
603d8606c27SBarry Smith  PetscCallA(SNESSolve(snes, PETSC_NULL_VEC, x, ierr))
604d8606c27SBarry Smith  PetscCallA(SNESGetIterationNumber(snes, its, ierr))
60524fb275aSStefano Zampini  write (outputString, *) its
60624fb275aSStefano Zampini  PetscCallA(PetscPrintf(PETSC_COMM_WORLD, 'Number of SNES iterations = '//trim(outputString)//'\n', ierr))
607c4762a1bSJed Brown
608c4762a1bSJed Brown!  PetscDraw contour plot of solution
609c4762a1bSJed Brown
610ce78bad3SBarry Smith  xl = 300
611ce78bad3SBarry Smith  yl = 0
612ce78bad3SBarry Smith  width = 300
613ce78bad3SBarry Smith  height = 300
614ce78bad3SBarry Smith  PetscCallA(PetscDrawCreate(PETSC_COMM_WORLD, PETSC_NULL_CHARACTER, 'Solution', xl, yl, width, height, draw, ierr))
615d8606c27SBarry Smith  PetscCallA(PetscDrawSetFromOptions(draw, ierr))
616c4762a1bSJed Brown
617ce78bad3SBarry Smith  PetscCallA(VecGetArrayRead(x, lx_v, ierr))
618ce78bad3SBarry Smith  imx = int(mx, kind=kind(imx))
619ce78bad3SBarry Smith  imy = int(my, kind=kind(imy))
620ce78bad3SBarry Smith  PetscCallA(PetscDrawTensorContour(draw, imx, imy, PETSC_NULL_REAL_ARRAY, PETSC_NULL_REAL_ARRAY, lx_v, ierr))
621ce78bad3SBarry Smith  PetscCallA(VecRestoreArrayRead(x, lx_v, ierr))
622c4762a1bSJed Brown
623c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
624c4762a1bSJed Brown!  Free work space.  All PETSc objects should be destroyed when they
625c4762a1bSJed Brown!  are no longer needed.
626c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
627c4762a1bSJed Brown
628d8606c27SBarry Smith  if (.not. matrix_free) PetscCallA(MatDestroy(J, ierr))
629d8606c27SBarry Smith  if (fd_coloring) PetscCallA(MatFDColoringDestroy(fdcoloring, ierr))
630c4762a1bSJed Brown
631d8606c27SBarry Smith  PetscCallA(VecDestroy(x, ierr))
632d8606c27SBarry Smith  PetscCallA(VecDestroy(r, ierr))
633d8606c27SBarry Smith  PetscCallA(SNESDestroy(snes, ierr))
634d8606c27SBarry Smith  PetscCallA(PetscDrawDestroy(draw, ierr))
635d8606c27SBarry Smith  PetscCallA(PetscFinalize(ierr))
636c4762a1bSJed Brownend
637c4762a1bSJed Brown!
638c4762a1bSJed Brown!/*TEST
639c4762a1bSJed Brown!
640c4762a1bSJed Brown!   build:
641ce78bad3SBarry Smith!      requires: !single !complex
642c4762a1bSJed Brown!
643c4762a1bSJed Brown!   test:
644c4762a1bSJed Brown!      args: -snes_monitor_short -nox -snes_type newtontr -ksp_gmres_cgs_refinement_type refine_always
645c4762a1bSJed Brown!
646c4762a1bSJed Brown!   test:
647c4762a1bSJed Brown!      suffix: 2
648c4762a1bSJed Brown!      args: -snes_monitor_short -nox -snes_fd -ksp_gmres_cgs_refinement_type refine_always
649c4762a1bSJed Brown!
650c4762a1bSJed Brown!   test:
651c4762a1bSJed Brown!      suffix: 3
652c4762a1bSJed Brown!      args: -snes_monitor_short -nox -snes_fd_coloring -mat_coloring_type sl -ksp_gmres_cgs_refinement_type refine_always
653c4762a1bSJed Brown!      filter: sort -b
654c4762a1bSJed Brown!      filter_output: sort -b
655c4762a1bSJed Brown!
656c4762a1bSJed Brown!   test:
657c4762a1bSJed Brown!     suffix: 4
658c4762a1bSJed Brown!     args: -pc -par 6.807 -nox
659c4762a1bSJed Brown!
660c4762a1bSJed Brown!TEST*/
661