xref: /petsc/src/ts/tutorials/ex1f.F90 (revision 5d83a8b16d06840f96948f1a43aa9c83c769a60a)
1d8606c27SBarry Smith!
2d8606c27SBarry Smith!   Solves the time dependent Bratu problem using pseudo-timestepping
3d8606c27SBarry Smith!
4d8606c27SBarry Smith!   This code demonstrates how one may solve a nonlinear problem
5d8606c27SBarry Smith!   with pseudo-timestepping. In this simple example, the pseudo-timestep
6d8606c27SBarry Smith!   is the same for all grid points, i.e., this is equivalent to using
7d8606c27SBarry Smith!   the backward Euler method with a variable timestep.
8d8606c27SBarry Smith!
9d8606c27SBarry Smith!   Note: This example does not require pseudo-timestepping since it
10d8606c27SBarry Smith!   is an easy nonlinear problem, but it is included to demonstrate how
11d8606c27SBarry Smith!   the pseudo-timestepping may be done.
12d8606c27SBarry Smith!
13d8606c27SBarry Smith!   See snes/tutorials/ex4.c[ex4f.F] and
14d8606c27SBarry Smith!   snes/tutorials/ex5.c[ex5f.F] where the problem is described
15d8606c27SBarry Smith!   and solved using the method of Newton alone.
16d8606c27SBarry Smith!
17d8606c27SBarry Smith!
18d8606c27SBarry Smith!23456789012345678901234567890123456789012345678901234567890123456789012
19d8606c27SBarry Smith      program main
20d8606c27SBarry Smith#include <petsc/finclude/petscts.h>
21d8606c27SBarry Smith      use petscts
22d8606c27SBarry Smith      implicit none
23d8606c27SBarry Smith
24d8606c27SBarry Smith!
25d8606c27SBarry Smith!  Create an application context to contain data needed by the
26d8606c27SBarry Smith!  application-provided call-back routines, FormJacobian() and
27d8606c27SBarry Smith!  FormFunction(). We use a double precision array with three
28d8606c27SBarry Smith!  entries indexed by param, lmx, lmy.
29d8606c27SBarry Smith!
30d8606c27SBarry Smith      PetscReal user(3)
31d8606c27SBarry Smith      PetscInt          param,lmx,lmy,i5
32d8606c27SBarry Smith      parameter (param = 1,lmx = 2,lmy = 3)
33d8606c27SBarry Smith!
34d8606c27SBarry Smith!   User-defined routines
35d8606c27SBarry Smith!
36d8606c27SBarry Smith      external FormJacobian,FormFunction
37d8606c27SBarry Smith!
38d8606c27SBarry Smith!   Data for problem
39d8606c27SBarry Smith!
40d8606c27SBarry Smith      TS                ts
41d8606c27SBarry Smith      Vec               x,r
42d8606c27SBarry Smith      Mat               J
43d8606c27SBarry Smith      PetscInt           its,N,i1000,itmp
44d8606c27SBarry Smith      PetscBool  flg
45d8606c27SBarry Smith      PetscErrorCode      ierr
46d8606c27SBarry Smith      PetscReal  param_max,param_min,dt
47d8606c27SBarry Smith      PetscReal  tmax
48d8606c27SBarry Smith      PetscReal  ftime
49d8606c27SBarry Smith      TSConvergedReason reason
50d8606c27SBarry Smith
51d8606c27SBarry Smith      i5 = 5
52d8606c27SBarry Smith      param_max = 6.81
53d8606c27SBarry Smith      param_min = 0
54d8606c27SBarry Smith
55d8606c27SBarry Smith      PetscCallA(PetscInitialize(ierr))
56d8606c27SBarry Smith      user(lmx)        = 4
57d8606c27SBarry Smith      user(lmy)        = 4
58d8606c27SBarry Smith      user(param)      = 6.0
59d8606c27SBarry Smith
60d8606c27SBarry Smith!
61d8606c27SBarry Smith!     Allow user to set the grid dimensions and nonlinearity parameter at run-time
62d8606c27SBarry Smith!
63d8606c27SBarry Smith      PetscCallA(PetscOptionsGetReal(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-mx',user(lmx),flg,ierr))
64d8606c27SBarry Smith      itmp = 4
65d8606c27SBarry Smith      PetscCallA(PetscOptionsGetInt(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-my',itmp,flg,ierr))
66d8606c27SBarry Smith      user(lmy) = itmp
67d8606c27SBarry Smith      PetscCallA(PetscOptionsGetReal(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-param',user(param),flg,ierr))
68d8606c27SBarry Smith      if (user(param) .ge. param_max .or. user(param) .le. param_min) then
69d8606c27SBarry Smith        print*,'Parameter is out of range'
70d8606c27SBarry Smith      endif
71d8606c27SBarry Smith      if (user(lmx) .gt. user(lmy)) then
72d8606c27SBarry Smith        dt = .5/user(lmx)
73d8606c27SBarry Smith      else
74d8606c27SBarry Smith        dt = .5/user(lmy)
75d8606c27SBarry Smith      endif
76d8606c27SBarry Smith      PetscCallA(PetscOptionsGetReal(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-dt',dt,flg,ierr))
77d8606c27SBarry Smith      N          = int(user(lmx)*user(lmy))
78d8606c27SBarry Smith
79d8606c27SBarry Smith!
80d8606c27SBarry Smith!      Create vectors to hold the solution and function value
81d8606c27SBarry Smith!
82d8606c27SBarry Smith      PetscCallA(VecCreateSeq(PETSC_COMM_SELF,N,x,ierr))
83d8606c27SBarry Smith      PetscCallA(VecDuplicate(x,r,ierr))
84d8606c27SBarry Smith
85d8606c27SBarry Smith!
86d8606c27SBarry Smith!    Create matrix to hold Jacobian. Preallocate 5 nonzeros per row
87d8606c27SBarry Smith!    in the sparse matrix. Note that this is not the optimal strategy see
88d8606c27SBarry Smith!    the Performance chapter of the users manual for information on
89d8606c27SBarry Smith!    preallocating memory in sparse matrices.
90d8606c27SBarry Smith!
91d8606c27SBarry Smith      i5 = 5
92*5d83a8b1SBarry Smith      PetscCallA(MatCreateSeqAIJ(PETSC_COMM_SELF,N,N,i5,PETSC_NULL_INTEGER_ARRAY,J,ierr))
93d8606c27SBarry Smith
94d8606c27SBarry Smith!
95d8606c27SBarry Smith!     Create timestepper context
96d8606c27SBarry Smith!
97d8606c27SBarry Smith
98d8606c27SBarry Smith      PetscCallA(TSCreate(PETSC_COMM_WORLD,ts,ierr))
99d8606c27SBarry Smith      PetscCallA(TSSetProblemType(ts,TS_NONLINEAR,ierr))
100d8606c27SBarry Smith
101d8606c27SBarry Smith!
102d8606c27SBarry Smith!     Tell the timestepper context where to compute solutions
103d8606c27SBarry Smith!
104d8606c27SBarry Smith
105d8606c27SBarry Smith      PetscCallA(TSSetSolution(ts,x,ierr))
106d8606c27SBarry Smith
107d8606c27SBarry Smith!
108d8606c27SBarry Smith!    Provide the call-back for the nonlinear function we are
109d8606c27SBarry Smith!    evaluating. Thus whenever the timestepping routines need the
110d8606c27SBarry Smith!    function they will call this routine. Note the final argument
111d8606c27SBarry Smith!    is the application context used by the call-back functions.
112d8606c27SBarry Smith!
113d8606c27SBarry Smith
114d8606c27SBarry Smith      PetscCallA(TSSetRHSFunction(ts,PETSC_NULL_VEC,FormFunction,user,ierr))
115d8606c27SBarry Smith
116d8606c27SBarry Smith!
117d8606c27SBarry Smith!     Set the Jacobian matrix and the function used to compute
118d8606c27SBarry Smith!     Jacobians.
119d8606c27SBarry Smith!
120d8606c27SBarry Smith
121d8606c27SBarry Smith      PetscCallA(TSSetRHSJacobian(ts,J,J,FormJacobian,user,ierr))
122d8606c27SBarry Smith
123d8606c27SBarry Smith!
124d8606c27SBarry Smith!       For the initial guess for the problem
125d8606c27SBarry Smith!
126d8606c27SBarry Smith
127d8606c27SBarry Smith      PetscCallA(FormInitialGuess(x,user,ierr))
128d8606c27SBarry Smith
129d8606c27SBarry Smith!
130d8606c27SBarry Smith!       This indicates that we are using pseudo timestepping to
131d8606c27SBarry Smith!     find a steady state solution to the nonlinear problem.
132d8606c27SBarry Smith!
133d8606c27SBarry Smith
134d8606c27SBarry Smith      PetscCallA(TSSetType(ts,TSPSEUDO,ierr))
135d8606c27SBarry Smith
136d8606c27SBarry Smith!
137d8606c27SBarry Smith!       Set the initial time to start at (this is arbitrary for
138d8606c27SBarry Smith!     steady state problems and the initial timestep given above
139d8606c27SBarry Smith!
140d8606c27SBarry Smith
141d8606c27SBarry Smith      PetscCallA(TSSetTimeStep(ts,dt,ierr))
142d8606c27SBarry Smith
143d8606c27SBarry Smith!
144d8606c27SBarry Smith!      Set a large number of timesteps and final duration time
145d8606c27SBarry Smith!     to insure convergence to steady state.
146d8606c27SBarry Smith!
147d8606c27SBarry Smith      i1000 = 1000
148d8606c27SBarry Smith      tmax  = 1.e12
149d8606c27SBarry Smith      PetscCallA(TSSetMaxSteps(ts,i1000,ierr))
150d8606c27SBarry Smith      PetscCallA(TSSetMaxTime(ts,tmax,ierr))
151d8606c27SBarry Smith      PetscCallA(TSSetExactFinalTime(ts,TS_EXACTFINALTIME_STEPOVER,ierr))
152d8606c27SBarry Smith
153d8606c27SBarry Smith!
154d8606c27SBarry Smith!      Set any additional options from the options database. This
155d8606c27SBarry Smith!     includes all options for the nonlinear and linear solvers used
156d8606c27SBarry Smith!     internally the timestepping routines.
157d8606c27SBarry Smith!
158d8606c27SBarry Smith
159d8606c27SBarry Smith      PetscCallA(TSSetFromOptions(ts,ierr))
160d8606c27SBarry Smith
161d8606c27SBarry Smith      PetscCallA(TSSetUp(ts,ierr))
162d8606c27SBarry Smith
163d8606c27SBarry Smith!
164d8606c27SBarry Smith!      Perform the solve. This is where the timestepping takes place.
165d8606c27SBarry Smith!
166d8606c27SBarry Smith      PetscCallA(TSSolve(ts,x,ierr))
167d8606c27SBarry Smith      PetscCallA(TSGetSolveTime(ts,ftime,ierr))
168d8606c27SBarry Smith      PetscCallA(TSGetStepNumber(ts,its,ierr))
169d8606c27SBarry Smith      PetscCallA(TSGetConvergedReason(ts,reason,ierr))
170d8606c27SBarry Smith
171d8606c27SBarry Smith      write(6,100) its,ftime,reason
172d8606c27SBarry Smith 100  format('Number of pseudo time-steps ',i5,' final time ',1pe9.2,' reason ',i3)
173d8606c27SBarry Smith
174d8606c27SBarry Smith!
175d8606c27SBarry Smith!     Free the data structures constructed above
176d8606c27SBarry Smith!
177d8606c27SBarry Smith
178d8606c27SBarry Smith      PetscCallA(VecDestroy(x,ierr))
179d8606c27SBarry Smith      PetscCallA(VecDestroy(r,ierr))
180d8606c27SBarry Smith      PetscCallA(MatDestroy(J,ierr))
181d8606c27SBarry Smith      PetscCallA(TSDestroy(ts,ierr))
182d8606c27SBarry Smith      PetscCallA(PetscFinalize(ierr))
183d8606c27SBarry Smith      end
184d8606c27SBarry Smith
185d8606c27SBarry Smith!
186d8606c27SBarry Smith!  --------------------  Form initial approximation -----------------
187d8606c27SBarry Smith!
188d8606c27SBarry Smith      subroutine FormInitialGuess(X,user,ierr)
189d8606c27SBarry Smith      use petscts
190d8606c27SBarry Smith      implicit none
191d8606c27SBarry Smith
192d8606c27SBarry Smith      Vec              X
193d8606c27SBarry Smith      PetscReal user(3)
194d8606c27SBarry Smith      PetscInt  i,j,row,mx,my
195d8606c27SBarry Smith      PetscErrorCode ierr
196d8606c27SBarry Smith      PetscReal one,lambda
197d8606c27SBarry Smith      PetscReal temp1,temp,hx,hy
19842ce371bSBarry Smith      PetscScalar,pointer :: xx(:)
199d8606c27SBarry Smith      PetscInt          param,lmx,lmy
200d8606c27SBarry Smith      parameter (param = 1,lmx = 2,lmy = 3)
201d8606c27SBarry Smith
202d8606c27SBarry Smith      one = 1.0
203d8606c27SBarry Smith
204d8606c27SBarry Smith      mx     = int(user(lmx))
205d8606c27SBarry Smith      my     = int(user(lmy))
206d8606c27SBarry Smith      lambda = user(param)
207d8606c27SBarry Smith
208d8606c27SBarry Smith      hy    = one / (my-1)
209d8606c27SBarry Smith      hx    = one / (mx-1)
210d8606c27SBarry Smith
21142ce371bSBarry Smith      PetscCall(VecGetArrayF90(X,xx,ierr))
212d8606c27SBarry Smith      temp1 = lambda/(lambda + one)
213d8606c27SBarry Smith      do 10, j=1,my
214d8606c27SBarry Smith        temp = min(j-1,my-j)*hy
215d8606c27SBarry Smith        do 20 i=1,mx
216d8606c27SBarry Smith          row = i + (j-1)*mx
217d8606c27SBarry Smith          if (i .eq. 1 .or. j .eq. 1 .or. i .eq. mx .or. j .eq. my) then
21842ce371bSBarry Smith            xx(row) = 0.0
219d8606c27SBarry Smith          else
22042ce371bSBarry Smith            xx(row) = temp1*sqrt(min(min(i-1,mx-i)*hx,temp))
221d8606c27SBarry Smith          endif
222d8606c27SBarry Smith 20     continue
223d8606c27SBarry Smith 10   continue
22442ce371bSBarry Smith      PetscCall(VecRestoreArrayF90(X,xx,ierr))
225d8606c27SBarry Smith      end
226d8606c27SBarry Smith!
227d8606c27SBarry Smith!  --------------------  Evaluate Function F(x) ---------------------
228d8606c27SBarry Smith!
229d8606c27SBarry Smith      subroutine FormFunction(ts,t,X,F,user,ierr)
230d8606c27SBarry Smith      use petscts
231d8606c27SBarry Smith      implicit none
232d8606c27SBarry Smith
233d8606c27SBarry Smith      TS       ts
234d8606c27SBarry Smith      PetscReal  t
235d8606c27SBarry Smith      Vec               X,F
236d8606c27SBarry Smith      PetscReal  user(3)
237d8606c27SBarry Smith      PetscErrorCode     ierr
238d8606c27SBarry Smith      PetscInt         i,j,row,mx,my
239d8606c27SBarry Smith      PetscReal  two,lambda
240d8606c27SBarry Smith      PetscReal  hx,hy,hxdhy,hydhx
241d8606c27SBarry Smith      PetscScalar  ut,ub,ul,ur,u
242d8606c27SBarry Smith      PetscScalar  uxx,uyy,sc
24342ce371bSBarry Smith      PetscScalar,pointer :: xx(:), ff(:)
244d8606c27SBarry Smith      PetscInt     param,lmx,lmy
245d8606c27SBarry Smith      parameter (param = 1,lmx = 2,lmy = 3)
246d8606c27SBarry Smith
247d8606c27SBarry Smith      two = 2.0
248d8606c27SBarry Smith
249d8606c27SBarry Smith      mx     = int(user(lmx))
250d8606c27SBarry Smith      my     = int(user(lmy))
251d8606c27SBarry Smith      lambda = user(param)
252d8606c27SBarry Smith
253d8606c27SBarry Smith      hx    = 1.0 / real(mx-1)
254d8606c27SBarry Smith      hy    = 1.0 / real(my-1)
255d8606c27SBarry Smith      sc    = hx*hy
256d8606c27SBarry Smith      hxdhy = hx/hy
257d8606c27SBarry Smith      hydhx = hy/hx
258d8606c27SBarry Smith
25942ce371bSBarry Smith      PetscCall(VecGetArrayReadF90(X,xx,ierr))
26042ce371bSBarry Smith      PetscCall(VecGetArrayF90(F,ff,ierr))
261d8606c27SBarry Smith      do 10 j=1,my
262d8606c27SBarry Smith        do 20 i=1,mx
263d8606c27SBarry Smith          row = i + (j-1)*mx
264d8606c27SBarry Smith          if (i .eq. 1 .or. j .eq. 1 .or. i .eq. mx .or. j .eq. my) then
26542ce371bSBarry Smith            ff(row) = xx(row)
266d8606c27SBarry Smith          else
26742ce371bSBarry Smith            u       = xx(row)
26842ce371bSBarry Smith            ub      = xx(row - mx)
26942ce371bSBarry Smith            ul      = xx(row - 1)
27042ce371bSBarry Smith            ut      = xx(row + mx)
27142ce371bSBarry Smith            ur      = xx(row + 1)
272d8606c27SBarry Smith            uxx     = (-ur + two*u - ul)*hydhx
273d8606c27SBarry Smith            uyy     = (-ut + two*u - ub)*hxdhy
27442ce371bSBarry Smith            ff(row) = -uxx - uyy + sc*lambda*exp(u)
275d8606c27SBarry Smith         endif
276d8606c27SBarry Smith 20   continue
277d8606c27SBarry Smith 10   continue
278d8606c27SBarry Smith
27942ce371bSBarry Smith      PetscCall(VecRestoreArrayReadF90(X,xx,ierr))
28042ce371bSBarry Smith      PetscCall(VecRestoreArrayF90(F,ff,ierr))
281d8606c27SBarry Smith      end
282d8606c27SBarry Smith!
283d8606c27SBarry Smith!  --------------------  Evaluate Jacobian of F(x) --------------------
284d8606c27SBarry Smith!
285d8606c27SBarry Smith      subroutine FormJacobian(ts,ctime,X,JJ,B,user,ierr)
286d8606c27SBarry Smith      use petscts
287d8606c27SBarry Smith      implicit none
288d8606c27SBarry Smith
289d8606c27SBarry Smith      TS               ts
290d8606c27SBarry Smith      Vec              X
291d8606c27SBarry Smith      Mat              JJ,B
292d8606c27SBarry Smith      PetscReal user(3),ctime
293d8606c27SBarry Smith      PetscErrorCode   ierr
294d8606c27SBarry Smith      Mat              jac
295d8606c27SBarry Smith      PetscInt    i,j,row(1),mx,my
296d8606c27SBarry Smith      PetscInt    col(5),i1,i5
297d8606c27SBarry Smith      PetscScalar two,one,lambda
29842ce371bSBarry Smith      PetscScalar v(5),sc
29942ce371bSBarry Smith      PetscScalar,pointer :: xx(:)
300d8606c27SBarry Smith      PetscReal hx,hy,hxdhy,hydhx
301d8606c27SBarry Smith
302d8606c27SBarry Smith      PetscInt  param,lmx,lmy
303d8606c27SBarry Smith      parameter (param = 1,lmx = 2,lmy = 3)
304d8606c27SBarry Smith
305d8606c27SBarry Smith      i1 = 1
306d8606c27SBarry Smith      i5 = 5
307d8606c27SBarry Smith      jac = B
308d8606c27SBarry Smith      two = 2.0
309d8606c27SBarry Smith      one = 1.0
310d8606c27SBarry Smith
311d8606c27SBarry Smith      mx     = int(user(lmx))
312d8606c27SBarry Smith      my     = int(user(lmy))
313d8606c27SBarry Smith      lambda = user(param)
314d8606c27SBarry Smith
315d8606c27SBarry Smith      hx    = 1.0 / real(mx-1)
316d8606c27SBarry Smith      hy    = 1.0 / real(my-1)
317d8606c27SBarry Smith      sc    = hx*hy
318d8606c27SBarry Smith      hxdhy = hx/hy
319d8606c27SBarry Smith      hydhx = hy/hx
320d8606c27SBarry Smith
32142ce371bSBarry Smith      PetscCall(VecGetArrayReadF90(X,xx,ierr))
322d8606c27SBarry Smith      do 10 j=1,my
323d8606c27SBarry Smith        do 20 i=1,mx
324d8606c27SBarry Smith!
325d8606c27SBarry Smith!      When inserting into PETSc matrices, indices start at 0
326d8606c27SBarry Smith!
327d8606c27SBarry Smith          row(1) = i - 1 + (j-1)*mx
328d8606c27SBarry Smith          if (i .eq. 1 .or. j .eq. 1 .or. i .eq. mx .or. j .eq. my) then
329*5d83a8b1SBarry Smith            PetscCall(MatSetValues(jac,i1,[row],i1,[row],[one],INSERT_VALUES,ierr))
330d8606c27SBarry Smith          else
331d8606c27SBarry Smith            v(1)   = hxdhy
332d8606c27SBarry Smith            col(1) = row(1) - mx
333d8606c27SBarry Smith            v(2)   = hydhx
334d8606c27SBarry Smith            col(2) = row(1) - 1
33542ce371bSBarry Smith            v(3)   = -two*(hydhx+hxdhy)+sc*lambda*exp(xx(row(1)))
336d8606c27SBarry Smith            col(3) = row(1)
337d8606c27SBarry Smith            v(4)   = hydhx
338d8606c27SBarry Smith            col(4) = row(1) + 1
339d8606c27SBarry Smith            v(5)   = hxdhy
340d8606c27SBarry Smith            col(5) = row(1) + mx
341*5d83a8b1SBarry Smith            PetscCall(MatSetValues(jac,i1,[row],i5,col,v,INSERT_VALUES,ierr))
342d8606c27SBarry Smith          endif
343d8606c27SBarry Smith 20     continue
344d8606c27SBarry Smith 10   continue
345d8606c27SBarry Smith      PetscCall(MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY,ierr))
346d8606c27SBarry Smith      PetscCall(MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY,ierr))
34742ce371bSBarry Smith      PetscCall(VecRestoreArrayF90(X,xx,ierr))
348d8606c27SBarry Smith      end
349d8606c27SBarry Smith
350d8606c27SBarry Smith!/*TEST
351d8606c27SBarry Smith!
352d8606c27SBarry Smith!    test:
353d8606c27SBarry Smith!      TODO: broken
354d8606c27SBarry Smith!      args: -ksp_gmres_cgs_refinement_type refine_always -snes_type newtonls -ts_monitor_pseudo -ts_max_snes_failures 3 -ts_pseudo_frtol 1.e-5 -snes_stol 1e-5
355d8606c27SBarry Smith!
356d8606c27SBarry Smith!TEST*/
357